[英]How to input strings into an array in C?
我试图从用户那里获取输入(字符串)并将它们存储在一个数组中。但是在我运行这段代码后,程序立即崩溃了。
#include <stdio.h>
int main() {
int i;
char *word[3];
for(i=0;i<3;i++)
{
printf(" Enter a word: ");
scanf("%s", &word[i]);
}
printf("%s ", word[0]);
return 0;
}
在这一行:
scanf("%s", &word[i]);
您需要确保word[i]
指向某处,并且有足够的空间来占据输入的字符串。 由于word[i]
是一个char *
指针,您有时需要为此分配内存。 否则,它只是一个不指向任何地方的悬空指针。
如果您想坚持使用scanf()
,那么您可以预先使用malloc
分配一些空间。
malloc()
在堆上分配请求的内存,然后在最后返回一个void*
指针。
您可以像这样在代码中应用malloc()
:
size_t malloc_size = 100;
for (i = 0; i < 3; i++) {
word[i] = malloc(malloc_size * sizeof(char)); /* allocates 100 bytes */
printf("Enter word: ");
scanf("%99s", word[i]); /* Use %99s to avoid overflow */
/* No need to include & address, since word[i] is already a char* pointer */
}
注意:必须检查malloc()
返回值,因为它可以在不成功时返回NULL
。
此外,每当您使用malloc()
分配内存时,您必须在最后使用free
来释放请求的内存:
free(word[i]);
word[i] = NULL; /* safe to make sure pointer is no longer pointing anywhere */
读取字符串的更正确方法应该是使用fgets
。
char *fgets(char *str, int n, FILE *stream)
从输入流中读取一行,并将字节复制到char *str
,必须给定n
字节的大小作为它可以占用的空间阈值.
fgets 的注意事项:
\\n
字符。 可以轻松移除。NULL
。 如果没有读取字符,最后仍然返回NULL
。n
。stdin
或FILE *
。 以下是如何使用它从stdin
读取一行输入的示例:
char buffer[100]; /* statically declared buffer */
printf("Enter a string: ");
fgets(buffer, 100, stdin); /* read line of input into buffer. Needs error checking */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMSTR 3
#define BUFFSIZE 100
int main(void) {
char *words[NUMSTR];
char buffer[BUFFSIZE];
size_t i, count = 0, slen; /* can replace size_t with int if you prefer */
/* loops only for three input strings */
for (i = 0; i < NUMSTR; i++) {
/* read input of one string, with error checking */
printf("Enter a word: ");
if (fgets(buffer, BUFFSIZE, stdin) == NULL) {
fprintf(stderr, "Error reading string into buffer.\n");
exit(EXIT_FAILURE);
}
/* removing newline from buffer, along with checking for overflow from buffer */
slen = strlen(buffer);
if (slen > 0) {
if (buffer[slen-1] == '\n') {
buffer[slen-1] = '\0';
} else {
printf("Exceeded buffer length of %d.\n", BUFFSIZE);
exit(EXIT_FAILURE);
}
}
/* checking if nothing was entered */
if (!*buffer) {
printf("No string entered.\n");
exit(EXIT_FAILURE);
}
/* allocate space for `words[i]` and null terminator */
words[count] = malloc(strlen(buffer)+1);
/* checking return of malloc, very good to do this */
if (!words[count]) {
printf("Cannot allocate memory for string.\n");
exit(EXIT_FAILURE);
}
/* if everything is fine, copy over into your array of pointers */
strcpy(words[count], buffer);
/* increment count, ready for next space in array */
count++;
}
/* reading input is finished, now time to print and free the strings */
printf("\nYour strings:\n");
for (i = 0; i < count; i++) {
printf("words[%zu] = %s\n", i, words[i]);
free(words[i]);
words[i] = NULL;
}
return 0;
}
示例输入:
Enter a word: Hello
Enter a word: World
Enter a word: Woohoo
输出:
Your strings:
words[0] = Hello
words[1] = World
words[2] = Woohoo
这方面似乎有些混乱。 您的主要问题是您试图将每个单词写入您使用char *word[3];
声明的每个指针的地址char *word[3];
. (更不用说您没有在每个指针指向的位置分配存储空间——但是当您尝试使用&word[i]
写入每个指针的地址而不是指针本身时,您永远不会到达那里)
虽然你可以使用scanf
你会很快运行到与记录用户输入与很多陷阱的一个scanf
困扰所有新的C ++程序员(如无法处理'\\n'
留在输入缓冲区中,未能处理空白的字符串,未能限制读取/写入的字符数,未能验证读取或处理 EOF等... )
更好的方法是简单地使用fgets
,然后修剪fgets
读取并包含在它存储字符串的缓冲区中的'\\n'
。 一个简单的例子是:
#include <stdio.h>
#include <string.h>
#define NWDS 3 /* declare a constant for the maximum number of words */
int main (void) {
int i, n = 0;
char word[NWDS][50] = { "" }; /* provide storage or allocate */
for (i = 0; i < NWDS; i++) { /* for a max of NWDS */
printf ("Enter word : "); /* prompt */
if (!fgets (word[i], sizeof word[i], stdin)) /* read/validate */
break; /* protect against EOF */
size_t len = strlen (word[i]); /* get length */
if (word[i][len-1] == '\n') /* check for trailing '\n' */
word[i][--len] = 0; /* overwrite with nulbyte */
}
n = i; /* store number of words read */
putchar ('\n'); /* make it pretty */
for (i = 0; i < n; i++) /* output each word read */
printf (" word[%d] : %s\n", i, word[i]);
#if (defined _WIN32 || defined _WIN64)
getchar(); /* keep terminal open until keypress if on windows */
#endif
return 0;
}
通过在输入期间生成EOF
随时取消输入(在 Linux 上为ctrl + d或在 windoze 上为ctrl + z ),你会被覆盖。
示例使用/输出
$ ./bin/wordsread
Enter word : first word
Enter word : next word
Enter word : last word
word[0] : first word
word[1] : next word
word[2] : last word
仔细查看,考虑其他答案,如果您还有其他问题,请告诉我。
char *word[3]; // <-- this is an array of 3 dangling pointers, of type char*
// they still point nowhere, we later need to set them to some allocated location.
...
for(i=0;i<3;i++) {
word[i] = malloc(some_max_size * sizeof(char)); // <-- allocate space for your word
printf(" Enter a word: ");
scanf("%s", word[i]); // <-- not &word[i]; word[i] is already a char* pointer
}
您将 word 声明为指针数组 (char *word[3];)。 您必须分配内存来存储数据。 在赋值之前使用malloc或类似函数分配内存。
是的,代码崩溃是因为声明一个字符指针数组是不够的,您需要将指针设置为指向可以存储字符串的内存。
例如
const int maxLen = 32;
char* word[3] = {NULL,NULL,NULL};
word[i] = malloc(maxLen);
然后从键盘读取字符串,确保字符串不会太长,使用 fgets 和 maxLen:
printf("Enter a word:");
fgets(word[i],maxLen,stdin);
#include <stdio.h>
int main(){
int n;
int i=0;
scanf("%d",&n);
char arr[n];
while(n>i){
scanf("%s",&arr[i]);
i+=1;
}
while(n-i<n){
printf(" %c ",arr[n-i]);
i-=1;
}
}
代码char *word[3]
制作了一个 3 元素的指针数组!
看,您基本上已经创建了一个指针字符数组,因此您不能在每个指针中放入一个“字符串”,因为指针变量的类型是长十六进制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.