How to properly pass file path with from the command line? [closed]

女生的网名这么多〃 提交于 2020-01-06 08:01:12

问题


I've got a project about moving certain files from one directory to another. I have all finished except that the output is kind of strange. I am required to provide the destination path in the argsv array, but when I try to execute my code, it compiles and works but shows the wrong path containing many paths in one! Here is the relevant part, if you need more code I will add! Thank you in advance!

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");
}

So this is the main. The desired output is like this (I have many files):

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

and so on... but instead I get

./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 

and then even more garbage

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

and the first argument seems to have crashed as well...


回答1:


char *dest = argv[3]; 
strcat(dest, "/"); 
strcat(dest, files[i].justname); 

ouch you modify a string you do not own, do not do that, you probably write out of the string, work on a copy

replace

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");
}

by

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);
}



回答2:


This:

    char *dest = argv[3]

makes dest point to the same string that argv[3] does. That is, you have copied the pointer, not the data to which it points. When you subsequently modify that data through dest, you are modifying the argument itself. This is allowed, but poor form.

The bigger problem is what you actually do with it. This:

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

attempts to append data to the end of the argument string, but it is unsafe to assume (and it is probably incorrect in practice) that there is any free space in the pointed-to array in which to store the extra characters. If indeed there is not enough space then you produce undefined behavior.

Based on the code you did show and the behavior you describe, I speculate that what you did not show might include a similar assignment of another argument pointer to files[i].justname. Such an assignment is not inherently wrong, but it could easily make the manifestation of the UB more confusing than it already was.

In any case, if you want to form concatenations of the program arguments, then you need to reserve separate space for the result. You can do that with a large-enough automatic array, or with sufficiently large dynamically-allocated space. The latter might look like this:

    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

You can use strcpy() and strcat() instead if you prefer, but in this particular case I think sprintf() is clearer and cleaner.



来源:https://stackoverflow.com/questions/54278697/how-to-properly-pass-file-path-with-from-the-command-line

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!