我正在编写一个验证CSV文件的程序。格式的限制是:
编辑:
我根据反馈对代码进行了一些更改。有人可以解释一下while循环实际上在做什么吗?为什么交换机不工作?我现在得到所有输入的1。我可以在交换机中使用isdigit吗?
#include <ctype.h>
#include <stdio.h>
int main()
{
int c;
while ((c = getchar()) != EOF )
{
switch(c)
{
case'0':
printf("1");
break;
case'1':
printf("1");
break;
case'2':
printf("1");
break;
case'3':
printf("1");
break;
case'4':
printf("1");
break;
case'5':
printf("1");
break;
case'6':
printf("1");
break;
case'7':
printf("1");
break;
case'8':
printf("1");
break;
case'9':
printf("1");
break;
case',' :
printf("1");
break;
case'\n' :
printf("1");
break;
default :
printf("0");
break;
}
}
}
答案 0 :(得分:2)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void){
int ch;
while(EOF!=(ch=getchar())){
if(ch == ' '){
while(' '==(ch=getchar()));
goto CR;
}
if(isdigit(ch)){
while(','==(ch=getchar()))
if(isdigit(getchar()))
continue;
else
goto NG;
goto CR;
}
CR: if(ch != '\n')
goto NG;
}
printf("OK");
return EXIT_SUCCESS;
NG:
printf("NG");
return EXIT_FAILURE;
}
#if 0
while(EOF!=(ch=getchar())){
if(ch == ' '){
while(' '==(ch=getchar()));
} else if(isdigit(ch)){
while(','==(ch=getchar()))
if(!isdigit(getchar()))
break;//ch==','
}
if(ch != '\n')
goto NG;
}
#endif
答案 1 :(得分:0)
您的代码永远不会到达switch语句。
简而言之,递归就是:
int valid() /* This is the function definition. */
{
int c;
while((c = getchar()) != EOF) {
if(!valid(c)) { /* While not EOF you keep calling valid()
You also pass 'c' - which you can't get
as your function _definition_ does not have
any arguments. */
return 0; /* You never get here as valid() always, when EOF,
return 1 */
}
}
return 1; /* When EOF you never go _inside_ the while loop,
you return 1,
and back track of stack begins. */
switch(c) { ... /* You never get here. */
}
导致valid()
始终返回1
。
另请注意:
int valid(); /* This _declaration_ has no arguments thus indicating the
_definition_ of the function can have any number of
arguments. */
int valid(void); /* This would explicitly say that the _definition_ does not
take any arguments. */
int valid(int);
int valid(int foo); /* These would explicitly say the _definition takes
one int, and one int only. */
作为电话的一个例子:
file.csv:
0,2
1,2
调用堆栈步骤:
Down Up
01 main() 20 valid() return 1 so puts("1")
02 valid() 19 ... return 1
03 valid('0') 18 ... return 1
04 valid(',') 17 ... return 1
05 valid('2') 16 ... return 1
06 valid('\n') 15 ... return 1
07 valid('1') 14 Step 8 returns 1, so return 1
08 valid(',') 13 Step 9 returns 1, so return 1
09 valid('2') 12 Step 10 returns 1, so return 1
10 Now at EOF, 11 Never inside while as EOF, return 1.
v ^ Start popping calls from stack.
| |
+--------------+
答案 2 :(得分:0)
我不知道你的程序正在遵循什么逻辑,但这里有奇怪的递归
int valid()
{
int c;
while((c = getchar()) !=EOF) {
if (!valid(c)) {
您正在将int
传递给valid()
,理想情况不接受任何内容。
我认为此代码会进入无限旋转
即使您删除了递归调用,也会遇到普通的return 1
。我认为你也需要把它关掉
答案 3 :(得分:0)
查找isdigit()。这将取代你的switch语句中的一大块,并使其更短,以便更容易扫描。
此外,您可能希望一次读取一行(gets()/ fgets())而不是一次读取一个字符,然后对一行进行测试。
答案 4 :(得分:0)
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define bool int
#define false 0
#define true !false
// Rule:(SPACE* | [0-9](,[0-9])*)CR
bool isValid(char *str){
if(*str == '\n')
return true;
if(*str == ' '){
while(*++str == ' ');
if(*str == '\n')
return true;
else
return false;
}
if(isdigit(*str++)){
do{
if(*str == '\n')
return true;
}while(*str++ == ',' && isdigit(*str++));
return false;
}
return false;
}
#define BUFF_SIZE 128
int main(void){
#ifdef DEBUG
printf("\nEnd with comma:\n");
printf(isValid("1,2,3,\n") ? "OK" : "NG");
printf("\nStart with comma:\n");
printf(isValid(",1,2,3\n") ? "OK" : "NG");
printf("\nCR only:\n");
printf(isValid("\n") ? "OK" : "NG");
printf("\nSPACE and CR only:\n");
printf(isValid(" \n") ? "OK" : "NG");
printf("\nBelow zero:\n");
printf(isValid("-1\n") ? "OK" : "NG");
printf("\nGreater than nine:\n");
printf(isValid("10\n") ? "OK" : "NG");
printf("\nInclude two comma:\n");
printf(isValid("3,4,,5\n") ? "OK" : "NG");
printf("\nNormal pattern I:\n");
printf(isValid("9\n") ? "OK" : "NG");
printf("\nNormal pattern II:\n");
printf(isValid("3,4,5\n") ? "OK" : "NG");
#else
char line[BUFF_SIZE];
redo:
fgets(line, BUFF_SIZE, stdin);
if(NULL==strchr(line, '\n')){
fprintf(stderr,"You have exceeded the number of characters that can be entered.\n");
fflush(stdin);
goto redo;
}
if(isValid(line))
printf("OK\n");
else
printf("NG\n");
#endif
return 0;
}
答案 5 :(得分:0)
重写版本
#include <stdio.h>
#include <ctype.h>
#define bool int
#define false 0
#define true !false
// Rule:(SPACE* | [0-9](,[0-9])*)CR
bool isValid(FILE *fp){
int ch;
while(EOF!=(ch=fgetc(fp))){
if(ch == '\n')
continue;
if(ch == ' '){
while((ch=fgetc(fp)) == ' ');
if(ch == '\n')
continue;
else
return false;
}
if(isdigit(ch)){
do{
if((ch=fgetc(fp)) == '\n')
goto cont; //continue
}while(ch == ',' && isdigit(fgetc(fp)));
return false;
}
return false;
cont:;
}
return true;
}
int main(void){
FILE *file;
#ifdef DEBUG
file = fopen("testdata.csv","r");
#else
file = stdin;
#endif
if(isValid(file))
printf("OK");
else
printf("NG");
fclose(file);
return 0;
}
答案 6 :(得分:0)
#include <stdio.h>
#include <stdlib.h>
typedef enum STATUS {
START,SPC,NUM,COMMA,CR
} Status;
int main(void){
int ch;
Status pre_stat, stat;
pre_stat=stat=START;
while(EOF!=(ch=getchar())){
switch(ch){
case '\n':
stat = CR;
if(pre_stat == START || pre_stat == SPC || pre_stat == NUM){
//pre_stat = stat;
pre_stat = START;//line end move to line start, reset status
} else
goto NG;
break;
case ' ':
stat = SPC;
if(pre_stat == START || pre_stat == SPC){
pre_stat = stat;
} else
goto NG;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
stat = NUM;
if(pre_stat == START || pre_stat == COMMA){
pre_stat = stat;
} else
goto NG;
break;
case ',':
stat = COMMA;
if(pre_stat == NUM){
pre_stat = stat;
} else
goto NG;
break;
default:
goto NG;
}
}
printf("OK");
return EXIT_SUCCESS;
NG:
printf("NG");
return EXIT_FAILURE;
}