将由空格分隔的数字放入数组
我想让用户输入由空格分隔的数字,然后将每个值作为数组的元素存储.目前我有:
while ((c = getchar()) != 'n') { if (c != ' ') arr[i++] = c - '0'; } 但是,当然,这存储每个元素一个数字. 如果用户要输入: 10 567 92 3 我想要将值10存储在arr [0]中,然后在arr [1]等中存储567. 我应该使用scanf吗? 解决方法
有几种方法,具体取决于您希望代码的稳健性.
最直接的是使用scanf与%d转换说明符: while (scanf("%d",&a[i++]) == 1) /* empty loop */ ; %d转换说明符告诉scanf跳过任何前导的空格并读取到下一个非数字字符.返回值是转换和分配成功的次数.由于我们正在读取一个整数值,所以成功返回值应为1. 正如书面的,这有一些陷阱.首先,假设您的用户输入的数字大于数组的大小,以保持;如果你很幸运,你会立即获得访问冲突.如果不这样做,那么你会发现一些重要的东西会在以后引起问题(缓冲区溢出是常见的恶意软件漏洞). 所以你至少要添加代码,以确保不要超过数组的末尾: while (i < ARRAY_SIZE && scanf("%d",&a[i++]) == 1) /* empty loop */; 目前很好.但现在假设您的用户在其输入中输入非数字字符,例如12 3r5 67.如所写,循环将分配12到[0],3到a [1],然后它将在输入中看到r流,返回0并退出而不保存任何东西到[2].这里是一个微妙的bug蠕虫 – 即使没有任何东西被分配到一个[2],表达式我仍然被评估,所以你会认为你分配了一个[2],即使它包含垃圾值.所以你可能希望在增加我的时候,直到你知道你读了一个成功: while (i < ARRAY_SIZE && scanf("%d",&a[i]) == 1) i++; 理想情况下,您想完全拒绝3r5.我们可以在数字后面仔细阅读字符,并确保它是空格;如果不是,我们拒绝输入: #include <ctype.h> ... int tmp; char follow; int count; ... while (i < ARRAY_SIZE && (count = scanf("%d%c",&tmp,&follow)) > 0) { if (count == 2 && isspace(follow) || count == 1) { a[i++] = tmp; } else { printf ("Bad character detected: %cn",follow); break; } } 如果我们得到两个成功的转换,我们确保遵循一个空白字符 – 如果不是,我们打印错误并退出循环.如果我们得到一个成功的转换,那意味着输入号后没有字符(意味着我们在数字输入后打到EOF). 或者,我们可以读取每个输入值作为文本,并使用strtol进行转换,这也允许您捕获同样的问题(我的首选方法): #include <ctype.h> #include <stdlib.h> ... char buf[INT_DIGITS + 3]; // account for sign character,newline,and 0 terminator ... while(i < ARRAY_SIZE && fgets(buf,sizeof buf,stdin) != NULL) { char *follow; // note that follow is a pointer to char in this case int val = (int) strtol(buf,&follow,10); if (isspace(*follow) || *follow == 0) { a[i++] = val; } else { printf("%s is not a valid integer string; exiting...n",buf); break; } } 但等待更多! 假设你的用户是谁喜欢在代码中引发厌恶那些输入扭曲QA类型之一“只是为了看看会发生什么”,并进入了一些像123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890这显然是太大,以适应任何标准的整数类型.相信与否,scanf(“%d”,&val)将不会这样做,并且会将某些东西储存起来,但再次是您可能希望拒绝的输入. 如果你每行只允许一个值,这样就可以很容易地防范;如果有空格,则fgets将在目标缓冲区中存储一个换行字符,所以如果输入缓冲区中没有看到换行符,那么用户键入的内容比我们准备处理的更长一些: #include <string.h> ... while (i < ARRAY_SIZE && fgets(buf,stdin) != NULL) { char *newline = strchr(buf,'n'); if (!newline) { printf("Input value too longn"); /** * Read until we see a newline or EOF to clear out the input stream */ while (!newline && fgets(buf,stdin) != NULL) newline = strchr(buf,'n'); break; } ... } 如果要允许每行多个值,例如’10 20 30′,那么这会变得更困难.我们可以返回从输入中读取单个角色,并对每个角色进行理智检查(警告,未经测试): ... while (i < ARRAY_SIZE) { size_t j = 0; int c; while (j < sizeof buf - 1 && (c = getchar()) != EOF) && isdigit(c)) buf[j++] = c; buf[j] = 0; if (isdigit(c)) { printf("Input too long to handlen"); while ((c = getchar()) != EOF && c != 'n') // clear out input stream /* empty loop */ ; break; } else if (!isspace(c)) { if (isgraph(c) printf("Non-digit character %c seen in numeric inputn",c); else printf("Non-digit character %o seen in numeric inputn",c); while ((c = getchar()) != EOF && c != 'n') // clear out input stream /* empty loop */ break; } else a[i++] = (int) strtol(buffer,NULL,10); // no need for follow pointer,// since we've already checked // for non-digit characters. } 欢迎来到C的奇妙的交互式输入世界 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |