【问题标题】:How to properly pass file path with from the command line? [closed]如何从命令行正确传递文件路径? [关闭]
【发布时间】:2019-01-21 01:44:41
【问题描述】:

我有一个关于将某些文件从一个目录移动到另一个目录的项目。我已经完成了,只是输出有点奇怪。我需要在 argsv 数组中提供目标路径,但是当我尝试执行我的代码时,它会编译并工作,但会显示包含多个路径的错误路径!这是相关部分,如果您需要更多代码,我会添加!提前谢谢!

int main(int argc, char **argv)
{

int size = NFILES;
int index = -1;
file * files = malloc(size * sizeof(file));

listFilesRecursively(argv[1], &files, &size, &index);

if (index != -1) {
      int N = atoi(argv[2]);

if(N==1) qsort(files, index + 1, sizeof(file), compPathname);
else if(N==2) qsort(files, index + 1, sizeof(file), compPathsize);

for (int i = 0; i <= index; ++i) {
        char *dest = argv[3];
                strcat(dest, "/");
                strcat(dest, files[i].justname);
  printf("%s : %s : %ld\n", files[i].name, dest , (long)   files[i].file_info.st_size);
//  if(rename(files[i].name, dest)==0) printf("Success!\n"); else     printf("Failed!/n");
}

所以这是主要的。想要的输出是这样的(我有很多文件):

./copyto.c : /home/nik/copyto.c : 676
Success!
./mvfilrd.c : /home/nik/mvfilrd.c : 957
Success!
./sortall.c : /home/nik/sortall.c : 992
Success!

等等......但我得到了

./newdir/newfile.txt : /home/nik/Music/newfile.txt : 0
Success!
./newdir/3.exe : /home/nik/Music/newfile.txt/3.exe : 0
Failed!/n./newdir/compil : /home/nik/Music/newfile.txt/3.exe/test :     0
Failed!/n./newdir/2.c : /home/nik/Music/newfile.txt/3.exe/test/exe :         0 

然后更多的垃圾

Failed!/n./newf.exe : /home/nik/Music/newfile.txt/3.exe/test/exe    /1//Q�/~�dZ /�l�G^ /
                                                                                    ��`(/4�a^d /a.txt/range/1.txt/1.exe/print.exe/filrd.exeC/2.exre/filrd.exe/2.exe/fi.txt/fil.txt/dest.txt/sorcopy.c/filew.exe/.filer.c.swp    /progfilrd.exe/compile/myfile/.m

第一个参数似乎也崩溃了......

【问题讨论】:

  • 输入是什么(你的程序是怎么调用的)?什么是预期的输出?你得到的输出是什么?你的minimal reproducible example在哪里?
  • 我输入了源路径和目标路径以及其他内容。例如,我需要源路径的部分有效。所以基本上我提供源路径,获取文件,对它们做一些事情(实际上是排序)并将它们复制到另一个目录......复制部分看起来很奇怪......
  • 你修改了一个你不拥有的 argv[3],不要那样做,你可以写出字符串,在副本上工作。你确定 justname 只是名字吗?因为在另一个问题中 pathname 被保存,而不仅仅是名称
  • 如果我对函数内部的路径进行硬编码,一切正常...
  • char *dest = argv[3]; strcat(dest, "/"); ` 在argv[3] 指向的内存中没有位置,您正在写越界,溢出卡住(双关语)。您需要为字符串分配内存。 char *dest = malloc(strlen(argv[3] + sizeof("/") - 1 + strlen(files[i].justname) + 1) 或类似的。

标签: c arrays argv


【解决方案1】:
char *dest = argv[3]; 
strcat(dest, "/"); 
strcat(dest, files[i].justname); 

哎呀,你修改了一个你不拥有的字符串,不要那样做,你可能会写出字符串,在副本上工作

替换

for (int i = 0; i <= index; ++i) {
    char *dest = argv[3];
    strcat(dest, "/");
    strcat(dest, files[i].justname);
    printf("%s : %s : %ld\n", files[i].name, dest , (long)   files[i].file_info.st_size);
    if(rename(files[i].name, dest)==0) 
       printf("Success!\n");
    else
       printf("Failed!/n");
}

通过

for (int i = 0; i <= index; ++i) {
    size_t sz = strlen(argv[3]);
    char *dest = malloc(sz + strlen(files[i].justname) + 2);

    strcpy(dest, argv[3]);
    dest[sz] = '/';
    strcpy(dest + sz + 1, files[i].justname);

    printf("%s : %s : %ld\n", files[i].name, dest , (long)   files[i].file_info.st_size);
    if(rename(files[i].name, dest)==0)
      printf("Success!\n");
    else
      printf("Failed!/n");

    free(dest);
}

【讨论】:

  • 我更新了我的问题
  • @Nick 更新后是相同的代码,具有相同的缺陷。它没有任何区别。 char *dest = argv[3]; strcat(dest, "/"); strcat(dest, files[i].justname); 仍在您提供的代码中。
【解决方案2】:

这个:

    char *dest = argv[3]

使dest 指向与argv[3] 相同的字符串。也就是说,您复制了指针,而不是它指向的数据。当您随后通过dest 修改该数据时,您正在修改参数本身。这是允许的,但形式不佳。

更大的问题是你实际上用它做什么。这个:

  strcat(dest, "/"); 
  strcat(dest, files[i].justname);

尝试将数据附加到参数字符串的末尾,但假设指向的数组中有任何可用空间来存储额外字符是不安全的(并且在实践中可能是不正确的)。如果确实没有足够的空间,那么您会产生未定义的行为。

根据您显示的代码和您描述的行为,我推测您没有显示的内容可能包括将另一个参数指针分配给files[i].justname 的类似分配。这样的分配本身并没有错,但它很容易使 UB 的表现形式比以前更加混乱。

在任何情况下,如果你想形成程序参数的连接,那么你需要为结果保留单独的空间。您可以使用足够大的自动数组或足够大的动态分配空间来做到这一点。后者可能如下所示:

    size_t path_chars = strlen(argv[3]) + strlen(files[i].justname) + 2;
    char *path = malloc(path_chars);

    if (path) {
        sprintf(path, "%s/%s", argv[3], files[i].justname);
    } // else handle memory allocation failure

如果您愿意,可以改用strcpy()strcat(),但在这种特殊情况下,我认为sprintf() 更清晰。

【讨论】:

    猜你喜欢
    • 2016-04-08
    • 2018-12-10
    • 2012-09-24
    • 2018-04-05
    • 2019-06-14
    • 2011-09-28
    • 2016-08-11
    • 2019-02-15
    • 1970-01-01
    相关资源
    最近更新 更多