我想从控制台读取数据并输出到文本文件,每个结构类型变量保留N个字符。
文本文件类似于:
1 111 1 Peter 22 22 2 John Lays 3 3 3 Anne Belgs
我不知道我使用的是最正确的功能。
另外,我读(“ carro.name”)字数超过1个字(例如:John Lays)
struct estruturaCarro {
int id, potencia, avariado;
char name[11];
} carro;
...
//Read data to Text File:
...
printf("\n ID......:"); scanf("%d", &carro.id);
printf("\n Potencia:"); scanf("%d", &carro.potencia);
printf("\n Avariado:"); scanf("%d", &carro.avariado);
printf("\n NAME:"); scanf("%10[0-9a-zA-Z ]", carro.name); // or scanf("%[^\n]s",...)
fprintf(fp, "%-2d %-3d %-1d %-10s \n\n", carro.id, carro.potencia, carro.avariado, carro.name);
...
//Show File Text data:
...
int registos=0;
while(1)
{
fscanf(fp, "%d %d %d %-10s", &carro.id, &carro.potencia, &carro.avariado, carro.name);
if(feof(fp)){ break; }
printf("%-2d %-3d %-1d %-10s\n", carro.id, carro.potencia, carro.avariado, carro.name);
registos++;
}
printf("\nCarros=%d", registos);
答案 0 :(得分:1)
正如您在问题中所说,您不能使用 scanf 读取包含空格的复杂名称。
但是在搜索怎么做之前,需要先确定要做什么。
您可能不想记住开头和结尾的多余空格(包括换行符),并且名称不能为空。
但是在一个复杂的名字里面呢?如果用户输入John Lays
,您是否将名称保存两个空格,或者您想简化为仅包含一个?您是否需要管理其他特殊字符,例如'-'(John - Lays
/ John- Lays
/ John -Lays
读为John-Lays
吗?)。
如果输入字符串超过10个字符怎么办?只是为了停止阅读而让其余的内容供下次阅读还是绕过换行符?因为您在每次输入之前都打印一条消息,所以您显然希望每行输入一次,并且必须绕过其余行。
如果您不想按原样读取字符串,最好的方法可能是编写自己的读取字符串函数。
如果用户未输入 ID 或 Potencia 或 Avariado 的数字,您还必须决定该怎么办,当前您正在执行甚至无法检测到错误,这不是一个好方法。因此,在那种情况下,您是否放弃所有程序(退出程序),或者重做读取?可能您希望再读一遍,因为您需要绕过无效输入,但这意味着要绕开所有新行?
例如:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/* read an int memorizing its value in v,
return 0 in case of EOF else a non null value */
int readInt(const char * msg, int * v)
{
for (;;) {
fputs(msg, stdout);
if (scanf("%d", v) == 1)
return 1;
/* not a number or EOF, bypass all up to \n */
int c;
while ((c = fgetc(stdin)) != '\n')
if (c == EOF)
return 0;
puts("invalid value"); /* message may be also get in argument */
}
}
/* read a string up to a \n
remove extra spaces at the beginning and end
simplify internal multiple spaces
accept any character and do not manage in a special way characters like like '-'
a non empty string must be read
read at most sz-1 characters in s then place the null character (as fgets), sz must be > 1
if the line too long bypass the rest of the input up to \n
return 0 in case of EOF else a non null value */
int readStr(const char * msg, char * s, size_t sz)
{
fputs(msg, stdout);
/* read the first char bypassing spaces including \n */
if (scanf(" %c", s) == 0)
// EOF
return 0;
size_t index = 1;
int c;
sz -= 1;
while (index != sz) {
c = fgetc(stdin);
if ((c == EOF) || (c == '\n'))
break;
if (!isspace(c))
s[index++] = c;
else if (s[index - 1] != ' ')
s[index++] = ' ';
}
s[(s[index - 1] != ' ') ? index : index-1] = 0;
// bypass possible rest of the line
while ((c != EOF) && (c != '\n'))
c = fgetc(stdin);
return 1;
}
/* ******************* */
struct estruturaCarro {
int id, potencia, avariado;
char name[11];
} carro;
int main()
{
do {
if (!readInt("\n ID......:", &carro.id) ||
!readInt("\n Potencia:", &carro.potencia) ||
!readInt("\n Avariado:", &carro.avariado) ||
!readStr("\n NAME:", carro.name, sizeof(carro.name))) {
puts("EOF");
return -1;
}
else
printf("%-2d %-3d %-1d '%-10s' \n\n", carro.id, carro.potencia, carro.avariado, carro.name);
} while (strcmp(carro.name, "end"));
return 0;
}
编译和执行:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall r.c
pi@raspberrypi:/tmp $ ./a.out
ID......:aze
invalid value
ID......:qsd
invalid value
ID......:1
Potencia:2
Avariado:3
NAME:aze u iiiiiiiiiiiiiiiiii
1 2 3 'aze u iiii'
ID......:11
Potencia:22
Avariado:0
NAME: end
11 22 0 'end '
pi@raspberrypi:/tmp $
当您读入文件并认为它是通过fprintf(fp, "%-2d %-3d %-1d %-10s", ...)
生成的时:
char line[21]; /* each line has 20 characters newline included */
while (fgets(line, sizeof(line), fp) != NULL) {
if (sscanf(line, "%d %d %d", &carro.id, &carro.potencia, &carro.avariado) != 3)
/* abnormal case, invalid file */
break; /* anything else you want to do */
/* the string starts at the index 9 and has 10 characters out of the newline */
memcpy(carro.name, line + 9, 10);
carro.name[10] = 0;
/* ... */
}
请注意,如果名称的长度小于10个字符,则该名称的末尾应带有空格
或者您可以按照与标准输入类似的方式阅读。