1

这真让我抓狂。我编写了一个程序,它接受用户输入的文件名。它在我的 ~/documents/cs 目录中执行时按预期运行,但在我的 ~/documents/cs/assign5 目录中失败。这对我来说完全没有意义。为什么程序的行为会根据它所在的目录而有所不同?

在父目录中执行的良好输出:

./a.out - file2
Enter the filename: file1
FILE1
FILE2

assign5 目录的错误输出:

./a.out - file2
Enter the filename: file1
file1
n: No such file or directory

我什至尝试将 assign5 目录重命名为其他目录,并且效果很好。

该程序基本上采用两个命令行参数。如果存在“-”命令行参数,它会询问文件名。然后它将两个文件的内容打印到标准输出。这是程序失败的地方(仅在assign5目录中......)。似乎当程序在assign5目录中运行时,userInput变量存储的值是“n”而不是“file1”。为什么!?

if(strcmp(argv[1], "-") == 0) // use standard-in for input file 1
        {
            printf("Enter the filename: ");
            fflush(NULL);
            read(STDIN_FILENO, userInput, sizeof(userInput));
            userInput[strlen(userInput)-1] = '\0';
            if((input_file1 = open(userInput, O_RDONLY)) < 0)
            {
                perror(userInput);
                exit(1);
            }

更新:

我在名为“assign5”的目录中的远程 linux 服务器上运行完全相同的代码,并按预期编译和执行。那么,我的电脑有什么问题吗?

4

2 回答 2

4

不要使用read. 除非你知道自己在做什么,否则它会搞砸你所有的 I/O。

strlen从返回的输入read最多会导致SIGSEGV像您正在观察的那样未定义的行为。使用scanf.

scanf("%s", userInput); // will add a null terminator itself

如果您真的必须使用,read那么您需要scanf手动为您完成这项工作:

// reserve space for the null terminator
int bytes_read = read(STDIN_FILENO, userInput, sizeof(userInput) - 1);
if (bytes_read < 0) {
    perror("read");
    abort();
}         

// add the null terminator
userInput[bytes_read] = '\0';

// you will most likely have a newline in the input
while (isspace(userInput[bytes_read - 1]))
     userInput[--bytes_read] = '\0';

char * filename = userInput;

// you may have preceding spaces
while (isspace(*filename))
     filename++;

另请注意,由于未定义的原因,read可能会在读取整个输入之前返回,在这种情况下,理想情况下您应该再次调用它,直到它返回 0。scanf将为您完成这一切。

于 2013-11-01T15:14:17.543 回答
0

您正在用 '\0' 替换字符串中的最后一个字符,而不是像我怀疑的那样将 '\0' 附加到末尾:更改此行:

userInput[strlen(userInput)-1] = '\0';  

至:

userInput[strlen(userInput)] = '\0';  

我没有加载 linux 或 unix,但是这个 windows 代码很小,可以更好地说明我的建议:

#include <windows.h>
#include <ansi_c.h>
int main(void)
{
    DWORD len=260;
    LPTSTR lpBuffer;
    lpBuffer = malloc(260);
    GetCurrentDirectory(len, lpBuffer);

    lpBuffer[strlen(lpBuffer)]=0; //This works (although not necessary here
                                  //as GetCurrenentDirectory appends a '\0'
                                  //however, it is safe to do)

    lpBuffer[strlen(lpBuffer)-1]=0; //This will destroy the path information
                                    //by removing the last necessary char from 
    return 0;                       //your path string
}
于 2013-11-01T16:07:57.263 回答