我如何在C中修复它? [英] How do I fix that in C?
问题描述
我在 C
中使用 fsanf()
命令打开并读取仅包含两行的文本文件。在第一行是一个整数N数,在第二行是第一行所说的N个整数。
例如。
I use the fsanf()
command in C
to open and read a text file that contains only two lines. in first line is an integer N number, and in the second line is the N integer numbers that the first line says.
Eg.
-------------- nubmers.txt --------------
8 <-- we want 8 numbers for the 2nd line
16 8 96 46 8 213 5 16 <-- and we have 8 numbers! :)
如果第二行的数字多于或少于第一行,则整数表示会输出错误:
例如
Also if the second line have more or less numbers than the first line integer says will print an error:
Eg
-------------- nubmers.txt --------------
10
16 8 96 46 8 213 5 16 8 9 21 5 69 64 58 10 1 7 3 6
现在我将发布 fscanf()
代码:
Now I will post the fscanf()
code:
int num;
...
fscanf(fp,"%d",&num);
int i = 0;
int value = 0;
while (fscanf (fp, "%d", &value) == 1)
{
i++;
}
if (i > num)
{
printf ( "too many integers\n");
getchar();
return 1;
}
if (i < num)
{
printf ("not enough integers\n");
getchar();
return 1;
}
// if i equals num the code will get to this spot and will continue the debugging!
printf("work until now");
getchar();
return 0;
但问题是这个。
假设我们想要第二行的 4
数字。在第二行,我们有 3个数字
和 1个字母
。
例如
But the problem is this.
Lets say that we want 4
numbers for the second line. And In the second line we have 3 numbers
and 1 letter
.
Eg
-------------- nubmers.txt --------------
4
3 2 1 p
然后代码将读取该字母,它将显示我们的整数较少。 - 因为字母 p 不是整数。
我想收到一条错误消息,说我们在文本文件中有一个字母而不是数字
Then the code will read the letter and it'll show that we have less integers. -cause the letter p isn't a integer.
I want to get an error message that will say we have a letter in the text file and not a number
推荐答案
查看 fscanf [ ^ ]返回值。
Check out the fscanf[^] return value.
...
int success = 1;
for(int i = 0; success && (i < num); ++i)
{
if (fscanf(fp, "%d", &value))
{
// store value somewhere
// ...
}
else
{
printf("failed to read value or too little values");
success = 0;
}
}
if (success && fscanf(fp, "%d", &value))
{
printf("too many values");
}
...
干杯
Andi
Cheers
Andi
按顺序要做你想做的事你不应该通过fscan的%d格式读取值,而只是将字符串标记化,即将其细分为字符串。你可以用fscan的%s格式做到这一点,虽然我更喜欢其他方法。所以你的循环可能如下所示:
In order to do what you want you should not read the values via fscan's %d format, but just tokenize the string, i.e. subdivide it into strings. You can do that with fscan's %s format, although I would prefer other means. So your loop could look like:
// improved code, but not really good; see below
char str[100];
int value;
while (fscanf (fp, "%s", &str) == 1)
{
if (sscanf (str, "%d", &value) == 1)
i++;
else
printf ("Input <%s> is not a number", str);
}
有两个原因,为什么我不喜欢 scanf
函数:一个他们无法控制处理新行。换行符只是另一个空格字符。所以,如果您的输入是
There are two reasons, why I don't like the scanf
functions: For one they offer no control over handling newlines. A newline is just another whitespace character. So if your input would be
5
12 56 89
34 52
它将被视为合法投入。第二个原因是本质上不安全,因为你不能为%s格式指定输入缓冲区的长度(我在上面的例子中输入了100)。
作为scanf的替代方案,我更愿意先用 fgets
逐行读取输入行。然后通过 strtok
解析该行,最后通过 strtol
将其转换为整数。
it would be regarded as legal input. The second reason is that is inherently unsafe, as you cannot specify the length of your input buffer for the %s format (I put in 100 in the example above).
As an alternative to scanf I would prefer to first read the input line by line with fgets
. Then parse the line by strtok
, and finally convert it to integers by strtol
.
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char *fname ="E:\\00-C++\\VC2010\\PROJEKTE\\testfile.txt"; //filepath with the numbers
const int first_min =3; //min number count for line 2
const int first_max =12; //max number count for line 2
int first_number =0;
const long second_min =100;
const long second_max =1000000;
const int max_linelength =100; // make sure that real file-line-length is shorter than max_linelength
char line[max_linelength+5];
int lineno =0;
long number[first_max+5];
int ixnumber =0;
//--------------------------------------------------------------------------------
void funcPrintRuler()
{
printf("\n");
printf("\n.........1.........2.........3.........4.........5.........6.........7.........8.........9");
printf("\n123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
}
//--------------------------------------------------------------------------------
int funcOnlyDigitsOrSpaceAllowed(int lineno,char *line)
{
int kzdigit =0;
int pos =0;
char *p =line;
while (NULL!=*p)
{
pos++;
if (isdigit(*p)) {kzdigit=1;p++;continue;}
if (' '==*p) {p++;continue; }
funcPrintRuler();
printf("\n%s",line);
printf("\n%d.line: Only digits or space allowed. pos=%d",lineno,pos);
printf("\n");
return 0;
}
if (0==kzdigit)
{
funcPrintRuler();
printf("\n%s",line);
printf("\n%d.line: digits are missing",lineno);
printf("\n");
return 0;
}
return 1;
}
//--------------------------------------------------------------------------------
void funcGetNumbers(int lineno,char *line)
{
char *p =line;
ixnumber =0;
while (NULL!=*p )
{
if (ixnumber>=first_max) return ; // too many numbers
if (' '==*p) {p++; continue;}
number[ixnumber]=atol(p);
while( NULL!=*p && isdigit(*p)) {p++; continue;} // goto next number
ixnumber++;
p++;
}
}
//--------------------------------------------------------------------------------
int funcCheckLine1(int lineno,char *line)
{
funcGetNumbers(lineno,line);
if (1!=ixnumber )
{
printf("\n%d.line=%s<",lineno,line);
printf("\nonly one number allowed");
return 0;
};
if ( number[0]<first_min || number[0]>first_max )
{
printf("\n%d.line=%s<",lineno,line);
printf("\n%d.line contains number=%d, but must be >=%d and <=%d",lineno,number[0],first_min,first_max);
return 0;
}
return 1;
}
//--------------------------------------------------------------------------------
int funcCheckLine2(int lineno,char *line)
{
int i;
funcGetNumbers(lineno,line);
if (ixnumber!=first_number )
{
printf("\n%d.line=%s<",lineno,line);
printf("\nnumber count=%d, but must be %d",ixnumber, first_number);
return 0;
};
for(i=0; i<ixnumber;i++)
{
if (number[i]<second_min || number[i]>second_max )
{
printf("\n%d.line=%s<",lineno,line);
printf("\nnumber %d=%d, but must be >=%d and <=%d",i+1,number[i],second_min,second_max);
return 0;
}
}
return 1;
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
int i;
FILE *fp;
int lg=0;
printf("START");
fp = fopen (fname, "r");
if (fp == NULL) { printf ("Cannot open: \n%s",fname); goto w_err;}
while (NULL != fgets(line, max_linelength, fp))
{
lineno++;
lg=strlen(line);
line[lg-1]='\0'; // remove '\n', only for printf line, not nessessary for read numbers
//printf("\n%d. line=%s<",lineno,line);
switch( lineno )
{
case 1:
if ( !funcOnlyDigitsOrSpaceAllowed(lineno,line) ) goto w_err;
if ( !funcCheckLine1(lineno,line) ) goto w_err;
first_number=number[0];
break;
case 2:
if ( !funcOnlyDigitsOrSpaceAllowed(lineno,line) ) goto w_err;
if ( !funcCheckLine2(lineno,line) ) goto w_err;
break;
default:
// do something
printf("\n%d.line=%s<",lineno,line);
}
}
fclose (fp);
w_ok:
printf("\n\nFile Content:");
printf("\nline 1 read %d=number count for line 2",first_number);
for (i=0; i<ixnumber; i++)
{
printf("\nline 2 read %d.number=%ld",i+1,number[i]);
}
printf("\nprogram OK");
getc(stdin); // only pause
exit(EXIT_SUCCESS);
w_err:
printf("\nprogram error");
getc(stdin);
exit(EXIT_FAILURE);
}
这篇关于我如何在C中修复它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!