我正在研究cat linux命令的实现。目前,当命令后没有传递任何参数时,它可以从标准输入中读取,并依次从多个文件中读取;但是当传递“-”作为参数时,它将打印先前的输出,而不是在某些情况下从标准输入中读取之前的输出。 。
例如,如果您传递-file1.txt-file2.txt-作为参数,那么一切都会按预期进行。它从标准输入中读取,输出file1.txt的内容,再次从stdin中读取,依此类推。但是,如果我删除了第一个'-',换句话说,如果第一个参数是文件,它将输出file1.txt的内容,然后从stdin读取,然后打印第二个文件的内容,然后而不是读取像以前一样从stdin中读取,第一次从stdin中读取时,它再次输出第二个文件的内容,然后输入内容,之后才开始正常运行。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_SIZE 1024
void readStdin(){
char buffer[BUF_SIZE];
while(fgets(buffer, BUF_SIZE, stdin)){ //reads from the standard input and prints the input
char *content = malloc(sizeof(char*)*BUF_SIZE);
if(content == NULL){ //failed to allocate memory
exit(1);
}
strcat(content, buffer);
//printf("buffer: %s", buffer);
//printf("content: %s", content);
printf(content);
memset(&content[0], 0, sizeof(*content));
free(content);
//printf("bufferEND: %s", buffer);
//printf("contentEND: %s", content);
}
}
void readArgs(int argc, char* argv[]){
FILE* fp;
char ch;
for (int i=1; i<argc; i++){
if (*argv[i] == '-'){
readStdin();
clearerr(stdin);
}
//else if ()
else {
fp = fopen(argv[i], "r");
if (fp==NULL){ //in case the file doesn't exist
printf("%s: No such file or directory\n", argv[i]);
exit(1);
}
while ((ch=fgetc(fp)) != EOF){
putchar(ch);
}
// fflush(stdin);
fclose(fp);
}
}
}
int main(int argc, char* argv[]){
if (argc<2){
readStdin();
return 0;
}
readArgs(argc, argv);
return 0;
}
有任何提示吗?
编辑:如果我以上述错误的方式从stdin读取后,如果我传递另一个文件后接另一个'-',则它不仅表现出相同的特征,而且不打印先前输出的第一个字符
答案 0 :(得分:0)
您的代码在这里以'-'作为参数
dls = "https://github.com/ItsMeLarry/Coursera_Capstone/raw/master/tl_2010_25 009_tract00.zip"
print('Downloading shapefile...')
r = requests.get(dls)
z = zipfile.ZipFile(io.BytesIO(r.content))
print("Done")
z.extractall(path='tmp/') # extract to folder
filenames = [y for y in sorted(z.namelist()) for ending in ['dbf',
'prj', 'shp', 'shx'] if y.endswith(ending)]
print(filenames)
dbf, prj, shp, shx = [filename for filename in filenames]
print(shp)
lynnmap = gpd.read_file(shp)
您的程序仅在接收到'-'作为参数时才调用if (*argv[i] == '-'){
readStdin();
clearerr(stdin);
}
,否则将输出参数文件。
当您传递readStdin()
时,这是5个参数(包括程序名称在内的6个参数)告诉您的程序“读取,输出file1.txt,读取,输出file2.txt,读取”
因此,当您删除第一个- file1.txt - file2.txt -
时,您还将删除第一个“读取”,而是告诉程序“输出file1.txt,读取,输出file2.txt,读取”
答案 1 :(得分:0)
按照该站点名称的优良传统,我怀疑您正在覆盖堆栈。使用malloc()分配内存时,该内存未初始化,这意味着它可以包含任何内容。结果,当您执行strcat(content,buffer)时,它将在content []的最后一个非空字符之后附加buffer []的内容,但是无法知道最后一个非空字符将在哪里是。它很容易超出content []的最后一个字节。欢迎来到C的世界。
在反思时,content []在堆上,因此您毕竟不会覆盖堆栈,但是我将此处保留在此处,因为您确实应该按照使用content []的方式修复它们。
此代码还有其他一些问题,可能是因为您习惯于使用其他语言。例如,printf(content)不是一个好主意,因为printf()的第一个参数被解释为格式字符串。如果它们在文件中的数据包含“%X”之类的内容,其中X是printf格式说明符,则printf()会将其解释为其格式语言的一部分。这可能会导致崩溃,并且也是安全漏洞的常见来源,因为任何人编写输入内容的人都可以使用格式说明符来读取/写入内存中的任意位置。
通常在C语言中,奇怪的或不确定的行为是由于内存处理错误引起的。您可能需要安装“ valgrind”工具,该工具可以帮助您找到这些东西。
我也看不出为什么要遍历整个带有内容[]的malloc / strcat / memset / free。直接打印buffer []会更简单,但是也许您对数据的将来有一些计划?