gpt4 book ai didi

c - 读取数据到文本文件并保留N个字符的输出

转载 作者:行者123 更新时间:2023-11-30 14:39:17 29 4
gpt4 key购买 nike

我想从控制台读取数据并输出到文本文件,每个结构类型变量保留 N 个字符。
文本文件类似于:

1  111 1 Peter22 22  2 John Lays3  3   3 Anne Belgs

I do not know if I'm using the most correct functions.
Also I can not read ("carro.name") more than 1 word (example: 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);

最佳答案

正如您在问题中所说,您不能使用 scanf 读取包含空格的复杂名称。

但在搜索如何之前,需要先决定做什么

您可能不想记住开头和结尾的多余空格(包括换行符),并且名称可能不能为空。

但是在复杂的名称中怎么办?如果用户输入 John Lays 您是否保存带有两个空格的名称,或者您想简化为只有一个空格?您是否必须管理其他特殊字符,例如“-”(将 John - Lays/John-Lays/John -Lays 读为 约翰-莱斯?)。

如果输入的字符串超过10个字符怎么办?只是停下来阅读,让其余部分进行下一次阅读,还是绕过换行符?因为您在每个输入之前打印一条消息,所以您显然希望每行都有一个输入,并且必须绕过该行的其余部分。

如果您不想按输入方式读取字符串,最好的方法可能是编写自己的读取字符串函数。

您还必须决定如果用户没有输入 IDPotenciaAvariado 数字该怎么办,目前您需要这样做甚至没有检测到错误,这不是一个好方法。那么在这种情况下,您是否中止所有操作(退出程序),或者重做读取?也许您更喜欢再次阅读,因为您需要绕过无效输入,但这意味着什么,绕过换行符之前的所有内容?

例如:

#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 个字符,则名称末尾有空格

或者您可以按照与之前在 stdin 上类似的方式进行读取。

关于c - 读取数据到文本文件并保留N个字符的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56152703/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com