【问题标题】:Why system call read() does not work when using user input为什么使用用户输入时系统调用 read() 不起作用
【发布时间】:2014-03-15 10:19:20
【问题描述】:

这是一个文件复制程序。

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>

int main()
{
    int fd1,fd2, ndata;
    char data[128];
    char *openname[1], *creatname[1]; 

    write(1, "Write open file name\n", 24); //user input

    read(0, openname, 30 );

    write(1, "Write creat file name\n", 25); //user input

    read(0, creatname,30);

    if((fd1 = open(openname, 0666))<0)
        {
            perror("cannot open the file");
            exit(1);
        }

    if((fd2 = creat(creatname,0666))<0)
        {
            perror("cannot create the file");
            exit(1);
        }

    while((ndata = read(fd1, data, 128))>0)
        {
            if((write(fd2, data, ndata))!=ndata)
                {
                    perror("cannot write the file");
                    exit(1); 
                } 
        }

    close(fd1);
    close(fd2); 

    write(1, "File copy is done.",19);

    return 0;

}

此代码不起作用。此代码打印错误消息:

cannot open the file.

但如果我将代码更改为:

if((fd1 = open("copy.c", 0666))<0)

还有这个:

if((fd2 = creat("real.c",0666))<0) 

运作良好。

为什么会发生这个错误?请回答。

【问题讨论】:

  • perror 将在cannot open the file 之后显示一条解释errno 的消息。对你有什么好处?
  • 对不起。那是 ENOENT :没有这样的文件或目录(POSIX.1)
  • 您使用的变量 opennamecreatname 错误。通过实现断点来检查你在这些变量中得到了什么。

标签: c linux unix system-calls


【解决方案1】:

您对opennamecreatname 的声明不正确。它们应该是:

char openname[31], creatname[31];

read() 没有在输入中添加空终止符,您需要添加它。 read() 返回读取的字节数。所以应该是:

int nread = read(0, openname, sizeof openname -1);
openname[nread-1] = '\0'; // subtract 1 to overwrite the newline

【讨论】:

    【解决方案2】:

    opennamecreatname 的类型错误,gcc -Wall -g 会警告您。声明例如char openname[256];

    你应该使用fgets(openname, sizeof(openname), stdin);来阅读它。

    如果您坚持使用read,请注意换行符(如果有)并添加一个零终止字节。

    还要学习使用gdb 调试器。

    【讨论】:

      【解决方案3】:

      read 级别很低。在这种情况下,它读取 30 个字节,包括您的输入键,也没有终止的空字节。所以文件名不会是你认为你输入的,它会包含额外的垃圾(甚至可能由于缺少空终止而使你的程序崩溃)。你想使用fgets or readline instead

      【讨论】:

        【解决方案4】:

        简而言之,通过使用read() 来输入文件名,这对自己来说是不必要的困难:它不会以 NUL 终止输入,不能保证读取您期望的字符数等。

        我的建议是坚持使用scanf()fgets()

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-09-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多