如何使用fscanf读取文件以初始化C中的值?

如何使用fscanf读取文件以初始化C中的值?,c,file,C,File,假设我的Client.txt文件如下所示。 客户端txt文件包含 客户的id、姓名、电子邮件和电话号码 现在的任务是读取客户机文件,并将id、姓名、电子邮件和电话号码保存到名为Client的结构中。 从这个客户机文本文件中,我将生成三个结构值,它们将被推送到结构列表中 但由于我只是在学习如何使用fscanf,并且在尝试练习fscanf时,我将任务缩小为: 如何读取文本并初始化第一个客户端的值 以下是我的尝试 int main(void){ FILE *fPtr; if((fPt

假设我的Client.txt文件如下所示。

客户端txt文件包含 客户的id、姓名、电子邮件和电话号码

现在的任务是读取客户机文件,并将id、姓名、电子邮件和电话号码保存到名为Client的结构中。 从这个客户机文本文件中,我将生成三个结构值,它们将被推送到结构列表中

但由于我只是在学习如何使用fscanf,并且在尝试练习fscanf时,我将任务缩小为: 如何读取文本并初始化第一个客户端的值

以下是我的尝试

int main(void){
    FILE *fPtr;
    if((fPtr = fopen("Client.txt"), "r") == NULL){
        puts("File could not be found.");
    }
    else{
        //First Client
        int clientId;//1111
        char clientName[30];//Name One
        char clientEmail[30];//Email.email.1
        char clientPhone[30];//111-111-1111

        //Initialize the first client.
        fscanf(fPtr, "%d%s%s%s", &clientId, clientName, clientEmail, clientPhone);

        //While not end of the file, initialize rest of the clients.
        while(!feof(fPtr)){
            //Have not yet implemented.
        }
        fclose(fPtr);

    }
}
如何将第一个客户端值初始化为

 clientId = 1111
 clientName[30] = Name One
 clientEmail[30] = Email.email.1
 clientPhone[30] = 111-111-1111

这里有一个解决方案,不是使用
scanf
,而是使用
getline

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>


typedef struct Client_s
{
        int clientId;
        char clientName[30];
        char clientEmail[30];
        char clientPhone[30];
} Client;

Client* get_next_client(FILE *f_ptr)
{
        Client *new_client = malloc(sizeof(Client));
        char *buff = malloc(30);
        size_t size = 30;
        int error = 0;

        if (new_client == NULL || buff == NULL)
                return NULL;

        if (getline(&buff, &size, f_ptr) <= 0)
                return NULL;
        new_client->clientId = atoi(buff);
        if (getline(&buff, &size, f_ptr) <= 0)
                return NULL;
        strncpy(new_client->clientName, buff, strlen(buff) - 1);
        if (getline(&buff, &size, f_ptr) <= 0)
                return NULL;
        strncpy(new_client->clientEmail, buff, strlen(buff) - 1);
        if (getline(&buff, &size, f_ptr) <= 0)
                return NULL;
        strncpy(new_client->clientPhone, buff, strlen(buff) - 1);

        free(buff);
        return new_client;
}

int main(int ac, char **av)
{
        FILE * f_ptr = fopen("Client.txt", "r");

        if (f_ptr == NULL)
        {
                write(2, "Could not open file\n", strlen("Could not open file\n"));
                return 1;
        }

        Client *client = get_next_client(f_ptr);
        while (client != NULL)
        {
                printf("%d\n", client->clientId);
                //handle client
                client = get_next_client(f_ptr);
        }

        fclose(f_ptr);

        return 0;
}
#包括
#包括
#包括
#包括
类型定义结构客户端
{
int clientId;
char clientName[30];
char-clientEmail[30];
char-clientPhone[30];
}客户;
客户端*get_next_客户端(文件*f_ptr)
{
客户*new_Client=malloc(sizeof(客户));
char*buff=malloc(30);
尺寸=30;
整数误差=0;
如果(新客户端==NULL | | buff==NULL)
返回NULL;
if(getline(&buff,&size,f_ptr)clientId=atoi(buff);
if(getline(&buff,&size,f_ptr)clientName,buff,strlen(buff)-1);
if(getline(&buff,&size,f_ptr)客户邮箱,buff,strlen(buff)-1);
if(getline(&buff,&size,f_ptr)客户端电话,buff,strlen(buff)-1);
免费(buff);
返回新客户;
}
内部主(内部ac,字符**av)
{
文件*f_ptr=fopen(“Client.txt”,“r”);
如果(f_ptr==NULL)
{
写入(2,“无法打开文件”,strlen(“无法打开文件”);
返回1;
}
Client*Client=get_next_Client(f_ptr);
while(客户端!=NULL)
{
printf(“%d\n”,客户端->客户端ID);
//处理客户
客户端=获取下一个客户端(f_ptr);
}
fclose(f_ptr);
返回0;
}
当你不再需要客户时,别忘了释放他们


希望能解决您的问题。

%s
匹配一个“单词”(即一系列非空白字符),因此它不能用于读取包含空格的字符串。(
f
scanf
非常精巧,虽然它倾向于在早期教授,但在许多方面它并不适合C新手。在这种情况下,您所拥有的看起来相当不错,除了一个问题:由
%s
指令扫描的字符串由空格分隔,因此您不能使用它来扫描包含空格的字符串空格,例如输入中的名称。若要一次读取一行,请使用
fgets
而不是
fscanf
(然后记得删除作为行的一部分读取的尾随换行符)。若要跳过前导空格,然后扫描所有内容到行的末尾,请使用
“%[^\n]”
(不要忽略前导空格字符)。还请注意,在未指定最大字段宽度的情况下扫描字符串应被视为完全错误,因为它使您极易受到缓冲区溢出攻击。因此,可能更像“%d%29[^\n]%29s%29s”`。如果输入的字段过长,这仍然会产生令人惊讶的结果,但不会溢出任何数组。
文件找不到。
是无用错误消息的典型示例。并且您将其打印到错误的流中。请使用
const char*path=“Client.txt”;如果((fPtr=fopen(path,“r”)==NULL){peror(path);exit(exit_FAILURE);
。感谢您的输入。您的回答极大地帮助了我思考更大的问题。但是,我使用“fgets”函数而不是“getline”来实现此功能函数。您认为使用fgets是一个坏主意吗?还是没有什么区别?使用
fgets
是可以的。不过,您通常需要去掉尾随的
\n
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>


typedef struct Client_s
{
        int clientId;
        char clientName[30];
        char clientEmail[30];
        char clientPhone[30];
} Client;

Client* get_next_client(FILE *f_ptr)
{
        Client *new_client = malloc(sizeof(Client));
        char *buff = malloc(30);
        size_t size = 30;
        int error = 0;

        if (new_client == NULL || buff == NULL)
                return NULL;

        if (getline(&buff, &size, f_ptr) <= 0)
                return NULL;
        new_client->clientId = atoi(buff);
        if (getline(&buff, &size, f_ptr) <= 0)
                return NULL;
        strncpy(new_client->clientName, buff, strlen(buff) - 1);
        if (getline(&buff, &size, f_ptr) <= 0)
                return NULL;
        strncpy(new_client->clientEmail, buff, strlen(buff) - 1);
        if (getline(&buff, &size, f_ptr) <= 0)
                return NULL;
        strncpy(new_client->clientPhone, buff, strlen(buff) - 1);

        free(buff);
        return new_client;
}

int main(int ac, char **av)
{
        FILE * f_ptr = fopen("Client.txt", "r");

        if (f_ptr == NULL)
        {
                write(2, "Could not open file\n", strlen("Could not open file\n"));
                return 1;
        }

        Client *client = get_next_client(f_ptr);
        while (client != NULL)
        {
                printf("%d\n", client->clientId);
                //handle client
                client = get_next_client(f_ptr);
        }

        fclose(f_ptr);

        return 0;
}