C 字符串数组和指针传递方法不起作用
Array of c-strings and pass by pointer method does not work
使用指针传递方法为 C 字符串数组分配新值无法正常工作。
在"LettersToCapital"方法内部,新值被正确地分配给C字符串数组,但是,一旦在方法之外读取C字符串数组内容,结果都是错误的。该函数应该做的就是将所有小写字母大写。我肯定做错了什么,但那会是什么?
如果在第 53 行,变量 tempStr 被替换为常量字符串文字,例如"aqua" 那么值在函数外保持不变。但是直接从 char 数组 (tempStr) 分配给 char 数组指针 (*(string +i)) 不会产生正确的结果。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void LettersToCapital(char **string, int size);
void ReadOutAOC(char **string, int size);
int main()
{
char *canadianProvinces[] = {"British Columbia", "Alberta", "Saskatchewan", "Manitoba", "Ontario", "Quebec", "New Brunswick", "Nova Scotia", "Prince Edward Island", "Newfoundland", "Yukon", "Northwest Territories", "Nunavut"};
int numOfCanProv = sizeof(canadianProvinces) / sizeof(int);
printf("\nNumber of Canadian provinces %d\n", numOfCanProv);
// printing all provinces before conversion
printf("\nBefore \"all to capital conversion\"\n\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
LettersToCapital(canadianProvinces, numOfCanProv);
// Temp(canadianProvinces);
// printing all provinces after conversion
printf("\nAfter \"all to capital conversion\"\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
}
void ReadOutAOC(char **string, int size)
{
printf("\n");
for(int i = 0; i < size; i++)
printf("String outside the assignment method[%d]: %s\n", i + 1, *(string + i));
}
void LettersToCapital(char **string, int size)
{
char tempStr[256];
for(int i = 0; i < size; i++)
{
for(int j = 0; j < strlen(*(string + i)); j++)
{
if(*(*(string + i) + j) > 96 && *(*(string + i) + j) < 123)
tempStr[j] = *(*(string + i) + j) - 32;
else
tempStr[j] = *(*(string + i) + j);
}
tempStr[strlen(*(string + i))] = '[=10=]';
*(string + i) = tempStr; // does not work
//*(string + i) = "aqua"; // try this instead
printf("String inside the assignment method[%d]: %s\n", i + 1, *(string + i));
}
}
预期输出应为:
之前"all to capital conversion"
不列颠哥伦比亚省
阿尔伯塔
萨斯喀彻温省
...
"all to capital conversion"
之后
不列颠哥伦比亚省
艾伯塔省
萨斯喀彻温省
...
以下代码:
- 干净地编译
- 执行所需的功能
- 注意访问数据字符串的正确方法
- 注意头文件的正确用法:
ctype.h
和函数:toupper()
- 未使用的变量,如
char tempStr[256];
和对该变量的所有引用都被删除
- 将由于尝试修改只读内存中的数据而导致 'seg fault' 事件
现在是错误代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void LettersToCapital(char **string, size_t size);
void ReadOutAOC(char **string, size_t size);
int main( void )
{
char *canadianProvinces[] =
{
"British Columbia",
"Alberta",
"Saskatchewan",
"Manitoba",
"Ontario",
"Quebec",
"New Brunswick",
"Nova Scotia",
"Prince Edward Island",
"Newfoundland",
"Yukon",
"Northwest Territories",
"Nunavut"
};
size_t numOfCanProv = sizeof(canadianProvinces) / sizeof(canadianProvinces[0]);
printf("\nNumber of Canadian provinces %lu\n", numOfCanProv);
// printing all provinces before conversion
printf("\nBefore \"all to capital conversion\"\n\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
LettersToCapital(canadianProvinces, numOfCanProv);
// Temp(canadianProvinces);
// printing all provinces after conversion
printf("\nAfter \"all to capital conversion\"\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
}
void ReadOutAOC(char **string, size_t size)
{
printf("\n");
for( size_t i = 0; i < size; i++)
printf("String outside the assignment method[%lu]: %s\n", i + 1, string[i] );
}
void LettersToCapital(char **string, size_t size)
{
for( size_t i = 0; i < size; i++)
{
size_t j;
for( j = 0; j < strlen( string[i] ); j++)
{
string[i][j] = (char)toupper( string[i][j] );
}
printf("String inside the assignment method[%lu]: %s\n", i + 1, string[i] );
}
}
运行 以上代码产生以下输出:
Before "all to capital conversion"
String outside the assignment method[1]: British Columbia
String outside the assignment method[2]: Alberta
String outside the assignment method[3]: Saskatchewan
String outside the assignment method[4]: Manitoba
String outside the assignment method[5]: Ontario
String outside the assignment method[6]: Quebec
String outside the assignment method[7]: New Brunswick
String outside the assignment method[8]: Nova Scotia
String outside the assignment method[9]: Prince Edward Island
String outside the assignment method[10]: Newfoundland
String outside the assignment method[11]: Yukon
String outside the assignment method[12]: Northwest Territories
String outside the assignment method[13]: Nunavut
Segmentation fault (core dumped)
使用 gdb 单步执行程序显示段错误事件的原因是这一行:
string[i][j] = (char)toupper( string[i][j] );
因为它正在尝试更改只读内存中的 value/byte/char
建议修改数据的定义为:
#define MAX_PROV_NAME_LEN 50
char canadianProvinces[][ MAX_PROV_NAME_LEN ] =
{
"British Columbia",
"Alberta",
"Saskatchewan",
"Manitoba",
"Ontario",
"Quebec",
"New Brunswick",
"Nova Scotia",
"Prince Edward Island",
"Newfoundland",
"Yukon",
"Northwest Territories",
"Nunavut"
};
然后调整其余代码以匹配即可解决问题。
更正后的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_PROV_NAME_LEN 50
void LettersToCapital(char string[][ MAX_PROV_NAME_LEN ], size_t size);
void ReadOutAOC(char string[][ MAX_PROV_NAME_LEN ], size_t size);
int main( void )
{
char canadianProvinces[][ MAX_PROV_NAME_LEN ] =
{
"British Columbia",
"Alberta",
"Saskatchewan",
"Manitoba",
"Ontario",
"Quebec",
"New Brunswick",
"Nova Scotia",
"Prince Edward Island",
"Newfoundland",
"Yukon",
"Northwest Territories",
"Nunavut"
};
size_t numOfCanProv = sizeof(canadianProvinces) / sizeof(canadianProvinces[0]);
printf("\nNumber of Canadian provinces %lu\n", numOfCanProv);
// printing all provinces before conversion
printf("\nBefore \"all to capital conversion\"\n\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
LettersToCapital(canadianProvinces, numOfCanProv);
// Temp(canadianProvinces);
// printing all provinces after conversion
printf("\nAfter \"all to capital conversion\"\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
}
void ReadOutAOC(char string[][ MAX_PROV_NAME_LEN ], size_t size)
{
printf("\n");
for( size_t i = 0; i < size; i++)
printf("String outside the assignment method[%lu]: %s\n", i + 1, string[i] );
}
void LettersToCapital(char string[][ MAX_PROV_NAME_LEN ], size_t size)
{
for( size_t i = 0; i < size; i++)
{
size_t j;
for( j = 0; j < strlen( string[i] ); j++)
{
string[i][j] = (char)toupper( string[i][j] );
}
printf("String inside the assignment method[%lu]: %s\n", i + 1, string[i] );
}
}
a 运行 更正后的代码导致以下输出:
Number of Canadian provinces 13
Before "all to capital conversion"
String outside the assignment method[1]: British Columbia
String outside the assignment method[2]: Alberta
String outside the assignment method[3]: Saskatchewan
String outside the assignment method[4]: Manitoba
String outside the assignment method[5]: Ontario
String outside the assignment method[6]: Quebec
String outside the assignment method[7]: New Brunswick
String outside the assignment method[8]: Nova Scotia
String outside the assignment method[9]: Prince Edward Island
String outside the assignment method[10]: Newfoundland
String outside the assignment method[11]: Yukon
String outside the assignment method[12]: Northwest Territories
String outside the assignment method[13]: Nunavut
String inside the assignment method[1]: BRITISH COLUMBIA
String inside the assignment method[2]: ALBERTA
String inside the assignment method[3]: SASKATCHEWAN
String inside the assignment method[4]: MANITOBA
String inside the assignment method[5]: ONTARIO
String inside the assignment method[6]: QUEBEC
String inside the assignment method[7]: NEW BRUNSWICK
String inside the assignment method[8]: NOVA SCOTIA
String inside the assignment method[9]: PRINCE EDWARD ISLAND
String inside the assignment method[10]: NEWFOUNDLAND
String inside the assignment method[11]: YUKON
String inside the assignment method[12]: NORTHWEST TERRITORIES
String inside the assignment method[13]: NUNAVUT
After "all to capital conversion"
String outside the assignment method[1]: BRITISH COLUMBIA
String outside the assignment method[2]: ALBERTA
String outside the assignment method[3]: SASKATCHEWAN
String outside the assignment method[4]: MANITOBA
String outside the assignment method[5]: ONTARIO
String outside the assignment method[6]: QUEBEC
String outside the assignment method[7]: NEW BRUNSWICK
String outside the assignment method[8]: NOVA SCOTIA
String outside the assignment method[9]: PRINCE EDWARD ISLAND
String outside the assignment method[10]: NEWFOUNDLAND
String outside the assignment method[11]: YUKON
String outside the assignment method[12]: NORTHWEST TERRITORIES
String outside the assignment method[13]: NUNAVUT
使用指针传递方法为 C 字符串数组分配新值无法正常工作。
在"LettersToCapital"方法内部,新值被正确地分配给C字符串数组,但是,一旦在方法之外读取C字符串数组内容,结果都是错误的。该函数应该做的就是将所有小写字母大写。我肯定做错了什么,但那会是什么?
如果在第 53 行,变量 tempStr 被替换为常量字符串文字,例如"aqua" 那么值在函数外保持不变。但是直接从 char 数组 (tempStr) 分配给 char 数组指针 (*(string +i)) 不会产生正确的结果。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void LettersToCapital(char **string, int size);
void ReadOutAOC(char **string, int size);
int main()
{
char *canadianProvinces[] = {"British Columbia", "Alberta", "Saskatchewan", "Manitoba", "Ontario", "Quebec", "New Brunswick", "Nova Scotia", "Prince Edward Island", "Newfoundland", "Yukon", "Northwest Territories", "Nunavut"};
int numOfCanProv = sizeof(canadianProvinces) / sizeof(int);
printf("\nNumber of Canadian provinces %d\n", numOfCanProv);
// printing all provinces before conversion
printf("\nBefore \"all to capital conversion\"\n\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
LettersToCapital(canadianProvinces, numOfCanProv);
// Temp(canadianProvinces);
// printing all provinces after conversion
printf("\nAfter \"all to capital conversion\"\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
}
void ReadOutAOC(char **string, int size)
{
printf("\n");
for(int i = 0; i < size; i++)
printf("String outside the assignment method[%d]: %s\n", i + 1, *(string + i));
}
void LettersToCapital(char **string, int size)
{
char tempStr[256];
for(int i = 0; i < size; i++)
{
for(int j = 0; j < strlen(*(string + i)); j++)
{
if(*(*(string + i) + j) > 96 && *(*(string + i) + j) < 123)
tempStr[j] = *(*(string + i) + j) - 32;
else
tempStr[j] = *(*(string + i) + j);
}
tempStr[strlen(*(string + i))] = '[=10=]';
*(string + i) = tempStr; // does not work
//*(string + i) = "aqua"; // try this instead
printf("String inside the assignment method[%d]: %s\n", i + 1, *(string + i));
}
}
预期输出应为:
之前"all to capital conversion"
不列颠哥伦比亚省
阿尔伯塔
萨斯喀彻温省
...
"all to capital conversion"
之后不列颠哥伦比亚省
艾伯塔省
萨斯喀彻温省
...
以下代码:
- 干净地编译
- 执行所需的功能
- 注意访问数据字符串的正确方法
- 注意头文件的正确用法:
ctype.h
和函数:toupper()
- 未使用的变量,如
char tempStr[256];
和对该变量的所有引用都被删除 - 将由于尝试修改只读内存中的数据而导致 'seg fault' 事件
现在是错误代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void LettersToCapital(char **string, size_t size);
void ReadOutAOC(char **string, size_t size);
int main( void )
{
char *canadianProvinces[] =
{
"British Columbia",
"Alberta",
"Saskatchewan",
"Manitoba",
"Ontario",
"Quebec",
"New Brunswick",
"Nova Scotia",
"Prince Edward Island",
"Newfoundland",
"Yukon",
"Northwest Territories",
"Nunavut"
};
size_t numOfCanProv = sizeof(canadianProvinces) / sizeof(canadianProvinces[0]);
printf("\nNumber of Canadian provinces %lu\n", numOfCanProv);
// printing all provinces before conversion
printf("\nBefore \"all to capital conversion\"\n\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
LettersToCapital(canadianProvinces, numOfCanProv);
// Temp(canadianProvinces);
// printing all provinces after conversion
printf("\nAfter \"all to capital conversion\"\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
}
void ReadOutAOC(char **string, size_t size)
{
printf("\n");
for( size_t i = 0; i < size; i++)
printf("String outside the assignment method[%lu]: %s\n", i + 1, string[i] );
}
void LettersToCapital(char **string, size_t size)
{
for( size_t i = 0; i < size; i++)
{
size_t j;
for( j = 0; j < strlen( string[i] ); j++)
{
string[i][j] = (char)toupper( string[i][j] );
}
printf("String inside the assignment method[%lu]: %s\n", i + 1, string[i] );
}
}
运行 以上代码产生以下输出:
Before "all to capital conversion"
String outside the assignment method[1]: British Columbia
String outside the assignment method[2]: Alberta
String outside the assignment method[3]: Saskatchewan
String outside the assignment method[4]: Manitoba
String outside the assignment method[5]: Ontario
String outside the assignment method[6]: Quebec
String outside the assignment method[7]: New Brunswick
String outside the assignment method[8]: Nova Scotia
String outside the assignment method[9]: Prince Edward Island
String outside the assignment method[10]: Newfoundland
String outside the assignment method[11]: Yukon
String outside the assignment method[12]: Northwest Territories
String outside the assignment method[13]: Nunavut
Segmentation fault (core dumped)
使用 gdb 单步执行程序显示段错误事件的原因是这一行:
string[i][j] = (char)toupper( string[i][j] );
因为它正在尝试更改只读内存中的 value/byte/char
建议修改数据的定义为:
#define MAX_PROV_NAME_LEN 50
char canadianProvinces[][ MAX_PROV_NAME_LEN ] =
{
"British Columbia",
"Alberta",
"Saskatchewan",
"Manitoba",
"Ontario",
"Quebec",
"New Brunswick",
"Nova Scotia",
"Prince Edward Island",
"Newfoundland",
"Yukon",
"Northwest Territories",
"Nunavut"
};
然后调整其余代码以匹配即可解决问题。
更正后的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_PROV_NAME_LEN 50
void LettersToCapital(char string[][ MAX_PROV_NAME_LEN ], size_t size);
void ReadOutAOC(char string[][ MAX_PROV_NAME_LEN ], size_t size);
int main( void )
{
char canadianProvinces[][ MAX_PROV_NAME_LEN ] =
{
"British Columbia",
"Alberta",
"Saskatchewan",
"Manitoba",
"Ontario",
"Quebec",
"New Brunswick",
"Nova Scotia",
"Prince Edward Island",
"Newfoundland",
"Yukon",
"Northwest Territories",
"Nunavut"
};
size_t numOfCanProv = sizeof(canadianProvinces) / sizeof(canadianProvinces[0]);
printf("\nNumber of Canadian provinces %lu\n", numOfCanProv);
// printing all provinces before conversion
printf("\nBefore \"all to capital conversion\"\n\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
LettersToCapital(canadianProvinces, numOfCanProv);
// Temp(canadianProvinces);
// printing all provinces after conversion
printf("\nAfter \"all to capital conversion\"\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
}
void ReadOutAOC(char string[][ MAX_PROV_NAME_LEN ], size_t size)
{
printf("\n");
for( size_t i = 0; i < size; i++)
printf("String outside the assignment method[%lu]: %s\n", i + 1, string[i] );
}
void LettersToCapital(char string[][ MAX_PROV_NAME_LEN ], size_t size)
{
for( size_t i = 0; i < size; i++)
{
size_t j;
for( j = 0; j < strlen( string[i] ); j++)
{
string[i][j] = (char)toupper( string[i][j] );
}
printf("String inside the assignment method[%lu]: %s\n", i + 1, string[i] );
}
}
a 运行 更正后的代码导致以下输出:
Number of Canadian provinces 13
Before "all to capital conversion"
String outside the assignment method[1]: British Columbia
String outside the assignment method[2]: Alberta
String outside the assignment method[3]: Saskatchewan
String outside the assignment method[4]: Manitoba
String outside the assignment method[5]: Ontario
String outside the assignment method[6]: Quebec
String outside the assignment method[7]: New Brunswick
String outside the assignment method[8]: Nova Scotia
String outside the assignment method[9]: Prince Edward Island
String outside the assignment method[10]: Newfoundland
String outside the assignment method[11]: Yukon
String outside the assignment method[12]: Northwest Territories
String outside the assignment method[13]: Nunavut
String inside the assignment method[1]: BRITISH COLUMBIA
String inside the assignment method[2]: ALBERTA
String inside the assignment method[3]: SASKATCHEWAN
String inside the assignment method[4]: MANITOBA
String inside the assignment method[5]: ONTARIO
String inside the assignment method[6]: QUEBEC
String inside the assignment method[7]: NEW BRUNSWICK
String inside the assignment method[8]: NOVA SCOTIA
String inside the assignment method[9]: PRINCE EDWARD ISLAND
String inside the assignment method[10]: NEWFOUNDLAND
String inside the assignment method[11]: YUKON
String inside the assignment method[12]: NORTHWEST TERRITORIES
String inside the assignment method[13]: NUNAVUT
After "all to capital conversion"
String outside the assignment method[1]: BRITISH COLUMBIA
String outside the assignment method[2]: ALBERTA
String outside the assignment method[3]: SASKATCHEWAN
String outside the assignment method[4]: MANITOBA
String outside the assignment method[5]: ONTARIO
String outside the assignment method[6]: QUEBEC
String outside the assignment method[7]: NEW BRUNSWICK
String outside the assignment method[8]: NOVA SCOTIA
String outside the assignment method[9]: PRINCE EDWARD ISLAND
String outside the assignment method[10]: NEWFOUNDLAND
String outside the assignment method[11]: YUKON
String outside the assignment method[12]: NORTHWEST TERRITORIES
String outside the assignment method[13]: NUNAVUT