我需要使用以下格式的C接收和输入来自标准输入的整数,并存储这些整数:“ 35:27,5,10”每行上有不确定数量的整数,行数也不确定。理想情况下,我希望有一个循环,可以在其中使用最近扫描的行中的值执行其他任务。我该如何扫描整数并将其存储在数组中,然后在扫描下一行时覆盖数组,依此类推,直到遇到EOF为止。
我想我必须同时使用scanf()和strtok(),但是我似乎不知道该怎么做。我也尝试过使用getchar(),但这只会使事情更加复杂。
答案 0 :(得分:1)
如果发现意外情况,此程序将读取该格式的文件(在stdin上),并发出错误消息。
//sumline.c sum integers on each line.
#include <stdio.h>
int main(){
int sum=0;
int rowcount=0;
char buf[30]="";
while(! feof(stdin) )
{
int in;
char sep[2];
if((scanf("%1[^0-9-+]",sep)) && !feof(stdin))
{
fgets(buf,30,stdin);
printf("unexpected %d char (%c,%30s)\n",sep[0],sep[0],buf);
return 1;
}
if( ! scanf("%d",&in))
{
printf("malformed int\n");
return 1;
}
if( feof(stdin) && rowcount == 0 )
{
return 0;
}
sum += in;
if( ! scanf("%1[,:.\n]",sep) && !feof(stdin))
{
fgets(buf,30,stdin);
printf("inexpected char %30s\n",buf);
return 1;
}
else
{
++rowcount;
}
if( sep[0]=='\n' && rowcount )
{
printf("sum=%d\n",sum);
sum=0;
rowcount=0;
}
if( feof(stdin) && rowcount == 0 )
{
return 0;
}
}
return 0;
}
答案 1 :(得分:0)
我想我必须同时使用scanf()和strtok()
使用fgets()
读取行,并使用sscanf()
扫描读取的行以获取整数:
#include <stddef.h> // size_t
#include <stdlib.h> // realloc(), free()
#include <stdio.h> // fgets(), sscanf(), printf(), puts(), fputs()
int main(void)
{
char line_buffer[100]; // a buffer for the current line
int *values_buffer = NULL; // pointer to memory to store the values in
size_t values_buffer_size = 0; // actual size of the value buffer
// while a line can be read from stdin ...
while (fgets(line_buffer, sizeof line_buffer / sizeof *line_buffer, stdin)) {
size_t num_values = 0; // to count the values we're able to extract
char *pos = line_buffer; // the current read-position inside line_buffer
// try to extract integers from the line_buffer at position pos:
for (int consumed = 0, value;
sscanf(pos, "%d%*[^0123456789]%n", &value, &consumed) >= 1;
pos += consumed)
{
// %*[^0123456789] discards a string not containing any digit
// %n yields the number of characters consumed
// if the value_buffer isn't big enough ...
if (num_values >= values_buffer_size) {
// resize it
int *tmp = realloc(values_buffer, (num_values + 1) * sizeof *tmp);
if (!tmp) {
fputs("Not enough memory. :(", stderr);
free(values_buffer);
return EXIT_FAILURE;
}
// ... and update it's size
values_buffer_size = num_values + 1;
values_buffer = tmp;
}
// save the current value in value_buffer
values_buffer[num_values++] = value;
}
// have fun with the values of the current line:
if (num_values) {
printf("Values: ");
for (size_t i = 0; i < num_values; ++i)
printf("%d ", values_buffer[i]);
putchar('\n');
} else puts("No values. :(\n");
}
// clean-up:
free(values_buffer);
if (ferror(stdin)) {
fputs("An input error occured. :(\n", stderr);
return EXIT_FAILURE;
}
else if (feof(stdin))
puts("EOF reached.\n");
}
答案 2 :(得分:0)
我想我必须同时使用scanf()和strtok()
否则我会假设:
用户可以在任何数字前输入“几乎无限”的零,或者在空白处输入很多,或者在小数点后输入很多零,或者...。这意味着您不能期望(例如)将一个数字的所有数字同时存储在RAM中;这意味着C提供的功能都不可用。
发生错误。解析文本时,无论文本来自用户(需要知道为什么不喜欢他们的文本)还是来自文件或另一台计算机(开发人员需要能够在其中使用),都应将明确和描述性的反馈视为强制性的查找/修复问题)。
最好是避免两个问题都在于状态机处于循环状态。也许吧:
int state = NEWLINE;
unsigned int lineNumber = 0;
unsigned int dataNumber;
while( ((c = getChar()) != EOF)) && (state != ERROR) ) {
switch(state) {
case NEWLINE:
lineNumber++;
if(isDigit(c) {
number = c - '0';
state = FIRST_NUMBER_STARTED;
dataNumber = 1;
} else {
printf("ERROR: Character at start of line is not a valid decimal digit\n");
state = ERROR;
}
break;
case FIRST_NUMBER_STARTED:
if(isDigit(c) {
digit = c - '0';
if(number > UINT_MAX/10) {
printf("ERROR: First number on line %u is too large\n", lineNumber);
state = ERROR;
} else {
number *= 10;
if(number > UINT_MAX - digit) {
printf("ERROR: First number on line %u is too large\n", lineNumber);
state = ERROR;
} else {
number += digit;
}
}
} else if(c == ';') {
state = COLON_FOUND;
} else {
printf("ERROR: Invalid character after first number on line\n");
state = ERROR;
}
break;
case COLON_FOUND:
if(isDigit(c) {
number = c - '0';
state = DATA_NUMBER_STARTED;
} else {
printf("ERROR: Character at start of data not a valid decimal digit\n");
state = ERROR;
}
break;
case DATA_NUMBER_STARTED:
if(isDigit(c) {
digit = c - '0';
if(number > UINT_MAX/10) {
printf("ERROR: Data number %u on line %u is too large\n", dataNumber, lineNumber);
state = ERROR;
} else {
number *= 10;
if(number > UINT_MAX - digit) {
printf("ERROR: Data number %u on line %u is too large\n", dataNumber, lineNumber);
state = ERROR;
} else {
number += digit;
}
}
} else if(c == ',') {
state = COMMA_FOUND;
} else if(c == '\n') {
state = NEW_LINE;
} else {
printf("ERROR: Invalid character after data number %u on line %u\n", dataNumber, lineNumber);
state = ERROR;
}
break;
case COMMA_FOUND:
dataNumber++;
if(isDigit(c) {
number = c - '0';
state = FIRST_NUMBER_STARTED;
} else if(c == '\n') {
printf("ERROR: Missing number after comma at end of line %u\n", lineNumber);
state = ERROR;
} else {
printf("ERROR: Invalid character after comma (after data number %u) on line %u\n", dataNumber-1, lineNumber);
}
break;
}
}
注意:示例代码根本不存储任何数据,也根本不处理空格(或小数点或...)(您可以为其添加更多代码和新状态),等等。它是“未经测试”的代码,仅供参考。