我正面临一个与c中打印一个字符串相关的问题。 该函数从用户获取两个变量 - 数字(应该从字符串打印字符的数字)和字符串。当我把字符串“Martin”并且数字是5时,输出是“i”。但是当数字大于字符串长度时出错了,我实际上不知道什么是错的。
PS。如果数字长于字符串大小,则应打印“Nothing”。
void printLetter() {
char * string = (char*)malloc(sizeof(char));
int n;
printf("Number:\n");
scanf("%i", &n);
printf("String:\n");
scanf("%s", string);
if(n > strlen(string)) {
printf("nothing");
} else {
printf("%c\n", string[n+1]);
}
free(string);
}
答案 0 :(得分:4)
这里不需要动态分配,因为你事先不知道字符串的长度,所以就这样做:
void printLetter() {
char string[100]; // example size 100
...
scanf("%99s", string); // read no more than your array can hold
}
一个有趣的练习是计算字符串的长度,根据需要动态分配动态空间(空终止符为+1),将string
复制到动态分配的空间,然后将其用作希望,然后释放它。
此外:
printf("%c\n", string[n+1]);
应写成:
printf("%c\n", string[n-1]);
因为你不想走出数组的边界(导致 Undefined Behavior ),或者在请求的角色旁边打印两个字符,因为当我要求第一个字符时,你应该打印string[0]
,当我要求第二个时,你应该打印string[1]
,依此类推。因此,当用户要求提供string[n-1]
字母时,您就会知道为什么我们需要打印n
。
顺便说一下,在处理 i ndex时,常常使用名为i
的变量,而不是n
。 ;)
在你的代码中,这个:
char * string = malloc(sizeof(char));
为只为一个字符分配内存,这是不好的,因为即使字符串只有一个字母,你会在哪里放置空终止符?你知道C中的字符串应该(几乎)总是NULL
终止。
为了为大小为N
的字符串动态分配内存,你应该这样做:
char * string = malloc((N + 1) * sizeof(char));
为N
字符分配空间,为NULL
终结符分配1。
答案 1 :(得分:1)
一些问题......
sizeof(char)通常为1个字节。因此malloc()只将一个字节的内存分配给字符串。也许需要更大的内存块? " Martin",例如,需要至少6个字节,加上字符串终止字符(总共7个字节)。
printf("%c \ n",string [n + 1])可能不太正确......
String: Martin\0
strlen= 6
Offset: 0123456
n = 5... [n+1] = 6
The character being output is the string terminator '\0' at index 6.
这可能会更好:
void printLetter() {
char * string = malloc(100 * sizeof(char));
int n;
printf("Number:\n");
scanf("%i", &n);
printf("String:\n");
scanf("%s", string);
if(n > strlen(string)) {
printf("nothing");
} else {
printf("%c\n", string[n-1]);
}
free(string);
}
答案 2 :(得分:-1)
您正面临缓冲区溢出。 看看这个问题,它会告诉你如何在这种情况下正确管理你的记忆:How to prevent scanf causing a buffer overflow in C?
或者,您可以询问字母数量并仅分配那么多内存+ 1.然后fgets(string, n,stdin);
因为您不需要其余的字符串: - )