Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
osx/unix/darwin路径中的转义空格,纯C_C_Macos_Unix_Darwin - Fatal编程技术网

osx/unix/darwin路径中的转义空格,纯C

osx/unix/darwin路径中的转义空格,纯C,c,macos,unix,darwin,C,Macos,Unix,Darwin,下面是一个简单的文件路径plain-C例程,它应该以编程方式扩展tildes并接受空白作为文件名中的合法字符。它适用于以下名称: ~/Test文件夹/Test.txt /Users/Shared/Test文件夹/Test.txt 但如果将文件图标拖放到终端,则似乎无法使用Apple建议的路径语法或Terminal.app生成的路径语法。app的窗口: /Users/Shared/Test\Folder/Test.txt 或 ~/Test\Folder/Test.txt 这是密码。很明显,我错过了

下面是一个简单的文件路径plain-C例程,它应该以编程方式扩展tildes并接受空白作为文件名中的合法字符。它适用于以下名称:

~/Test文件夹/Test.txt

/Users/Shared/Test文件夹/Test.txt

但如果将文件图标拖放到终端,则似乎无法使用Apple建议的路径语法或Terminal.app生成的路径语法。app的窗口:

/Users/Shared/Test\Folder/Test.txt

~/Test\Folder/Test.txt

这是密码。很明显,我错过了将“转义空白”替换为“纯空白”字符的例程。另一方面,对“\”的任何搜索例程都会导致编译器抱怨“未知转义序列”0x20(顺便说一句,在某些unix和linux系统中,它似乎是有效的空白代码,可能在OSX中不是这样?)

在plain-C和C-strings中是否有解决问题的方法,而不必处理苹果专有的CFStrings和NSStrings,因为我知道这些方法很简单?我只是负担不起在这个程序中使用这些。此外,请不要使用shell脚本、ruby、gawk、grep、perl、python等

提前谢谢

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wordexp.h>

void get_file_path(char path[])
{
    char *p;
    size_t len = 0;
    wordexp_t exp_result;

    printf("Enter file name: \n");    
    p = fgets(path, TEXT_SIZE, stdin);
    fflush(stdin);

    if(p != NULL)len = strlen(path);

    //get rid of newline characters
    for(p = path; p < path + len; p++){
        if(*p == '\n') *p = '\0';
    }

    if(path[0] == '~'){
        wordexp(path, &exp_result, 0);
        //printf("Num.expansions: %zd\n", exp_result.we_wordc);
        strcpy(path, exp_result.we_wordv[0]);        

        for(size_t i = 1; i < exp_result.we_wordc; i++){
        //printf("%s\n", exp_result.we_wordv[i]);
        strcat(path, " ");
        strcat(path, exp_result.we_wordv[i]);
        }
    wordfree(&exp_result);        
    }
    printf("File path: %s\n", path);
    return;
}

iharob是正确的,shell将
“\”
的无引号或双引号(“…”)外观转换为单个空格字符。结果空间不会分割单词。另一方面,只有当您首先向shell呈现这样的字符串时,才会发生这种情况。如果绕过shell,例如直接通过
exec()
函数族启动进程,或者字符串仅在程序内部使用,则不会发生这种情况

您似乎在区分shell语法和C语法方面有点困难。shell将反斜杠字符解释为通用转义字符,但C只识别特定的转义序列(所有转义序列都由反斜杠引入),并且
'\'
不在其中

另一方面,
'\\'
是其中之一:它表示一个反斜杠字符。因此,如果您正在为元素为反斜杠后跟空格的两个字符的字符串寻找字符串文字,那么在C中,它的拼写是
“\\”

更新:


除此之外,我认为您真正的问题是,仅当字符串的第一个字符是
~
时,程序才会执行扩展。在您介绍的测试运行中,情况并非如此。在这种情况下,如果扩展是无条件执行的,那么您的代码(或多或少)对我有效。

这个稍加修改的代码似乎可以完成这项工作。这是一个非常简单的解决方案,它将除文字反斜杠(\)之外的所有字符复制到辅助字符数组中,并在数组开头搜索平铺(~)并在找到平铺之前扩展路径,然后调整该数组的长度。感谢您的讨论、解释、建议和评论

bool get_file_path(char path[]){
char *p, *p1;
char path1[TEXT_SIZE];
size_t len = 0;
size_t len1, i;
wordexp_t exp_result;

printf("Enter file name: \n"); 
fix:
p = fgets(path, TEXT_SIZE, stdin); 
if(p == NULL) return false;   
else{
len = strlen(path);
if(strcmp(path,"\n") == 0)goto fix;
}
//get rid of "escaped whitespaces"
for(p = path, p1 = path1, len1 = len; p < path + len; p++, p1++){
    if(*p == '\\'){p++; len1--;}
    *p1 = *p;
}        
//get rid of newline characters
for(p1 = path1; p1 < path1 + len1; p1++){
    if(*p1 == '\n') *p1 = '\0';
}    
if(path1[0] == '~'){
    wordexp(path1, &exp_result, 0);
    //printf("Num.expansions: %zd\n", exp_result.we_wordc);
    strcpy(path1, exp_result.we_wordv[0]);        
    for(i = 1; i <  exp_result.we_wordc; i++){
    //printf("%s\n", exp_result.we_wordv[i]);
    strcat(path1, " ");
    strcat(path1, exp_result.we_wordv[i]);
    }
wordfree(&exp_result);        
}
strcpy(path, path1);    
printf("File path: %s\n", path);
return true;
}
bool获取文件路径(char路径[]){
字符*p,*p1;
字符路径1[文本大小];
尺寸长度=0;
尺寸1,i;
wordexp\u t exp\u结果;
printf(“输入文件名:\n”);
修正:
p=fgets(路径、文本大小、标准输入);
如果(p==NULL)返回false;
否则{
len=strlen(路径);
如果(strcmp(路径,“\n”)==0)转到修复;
}
//摆脱“转义空白”
对于(p=path,p1=path 1,len1=len;p
更新:


由于fflush(stdin)生成除Linux之外的未定义行为,因此额外的三行代码可以帮助清除stdin缓冲区中的“多余换行符”,而不是依赖fflush()来完成这项工作。

这并不是对代码主要问题的回答,而是代码的问题

如果(路径[0]='~'){
是一个微妙的问题

p = fgets(path, TEXT_SIZE, stdin);
...
if(path[0] == '~'){
p==NULL
发生
EOF
时,
path
的内容未在IO错误上定义,很可能是先前的缓冲区内容。最好将返回类型从
void
更改为
char*
,并在
p==NULL
时返回

p = fgets(path, TEXT_SIZE, stdin);
if (p == NULL) { 
  return NULL;
}

您不需要将
“\”
替换为
“”
因为这将由shell AFAIK完成。如果是这样的话,上述路径语法中的任何一种都会起作用。但既然不是这样,它似乎不是由shell完成的,不管是出于什么原因。请您自己尝试一下。我已经发布了代码。我没有Mac电脑,所以它可能会有不同的行为。Mac电脑使用bash作为默认的shell。它在那里的工作原理相同就像在Linux上一样。您测试过这个示例吗?我知道它应该在Linux上工作?但是,我有点担心,从理论上讨论bash是默认的shell,在任何一个系统上都应该工作,这似乎有点离题。还请注意,您需要转义一个文本反斜杠才能将其呈现给shell将文件拖放到
Terminal.app
是为了让shell使用,这绝对适用于该上下文。谢谢-你可能是对的。这个path参数与shell无关,因此我坚持使用纯C,我在区分C和bash方面没有问题。我只知道使用我们的人e我的程序将文件图标拖放到终端窗口,因为他们对复制长而复杂的文件路径时出现的打字错误感到沮丧,并且
p = fgets(path, TEXT_SIZE, stdin);
if (p == NULL) { 
  return NULL;
}