为什么 snprintf 在 %s 之后不读取?
Why is snprintf not reading after %s?
我正在尝试编写一个程序来检查 /home/user 目录 下是否存在某个位置。为此,我必须使用 whoami
命令获取用户名并将其输出添加到缓冲区以使用 locate
命令。
然而,即使 snprintf
读取了 whoami
命令,它也没有读取其余部分。我进行了几次搜索,得出的结果是 NULL
可能不会在字符串末尾终止。然而,我找不到如何手动终止它。我不确定是什么问题,所以,我在这里。
下面是更好地演示我的问题的代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <string.h>
char *readFile(char *);
bool check();
bool check() {
char path[200] = { 0 };
snprintf(path, 200, "/home/%s/.example", readFile("whoami"));
char lll[300] = { 0 };
snprintf(lll, 300, "locate %s", path);
char *buffer = readFile(lll);
if (strcmp(buffer, path) == 0) {
return true;
} else {
return false;
}
}
char *readFile(char cmd[200]) {
char cmd1[99999] = { 0 };
system("touch cmd");
snprintf(cmd1, 99999, "%s >> cmd", cmd);
system(cmd1);
FILE *f = fopen("cmd", "rt");
assert(f);
fseek(f, 0, SEEK_END);
long length = ftell(f);
fseek(f, 0, SEEK_SET);
char *buffer = (char *)malloc(length + 1);
buffer[length] = '[=10=]';
fread(buffer, 1, length, f);
fclose(f);
system("rm cmd");
return buffer;
}
int main() {
int x = check();
if (x == 1)
printf("There is a location like that");
else
printf("There isn't");
return 0;
}
whoami
命令打印出当前用户的名称,以换行符结束。将文件 cmd
读回 buffer
将包含相同的换行符。
path
字符串将是 "/home/USERNAME\n/.example"
。试图执行
locate /home/USERNAME\n/.example
可能会混淆 system
函数。
解决方案应该是去除 readFile
中的最后一个换行符。
您的 readFile
函数存在一些问题:
该名称具有误导性,应为 runCommand
或类似名称。
您将命令输出附加到 cmd
文件。如果 cmd
文件在您 运行 您的程序之前存在,这将导致意外结果。你应该改为写:
snprintf(cmd1, 99999, "%s > cmd", cmd);
命令输出可能有尾随换行符。你应该 trim 输出。
这是修改后的版本:
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *readFile(const char *cmd) {
/* construct the command */
size_t size = 4 + strlen(cmd) + 1;
char *cmd1 = malloc(size);
assert(cmd1);
snprintf(cmd1, size, "%s > cmd", cmd);
/* run the command */
system(cmd1);
free(cmd1);
/* read the output file */
FILE *f = fopen("cmd", "rt");
assert(f);
fseek(f, 0, SEEK_END);
long length = ftell(f);
fseek(f, 0, SEEK_SET);
char *buffer = malloc(length + 1);
buffer[length] = '[=11=]';
fread(buffer, 1, length, f);
fclose(f);
unlink("cmd");
/* trim trailing white space from the output */
while (length > 0 && isspace((unsigned char)buffer[length - 1])) {
buffer[--length] = '[=11=]';
}
/* trim leading white space from the output */
size_t i = 0;
while (isspace((unsigned char)buffer[i]) {
i++;
}
if (i > 0) {
memmove(buffer, buffer + i, length - i + 1);
}
return buffer;
}
因为 Linux 有一个你的主目录的快捷方式(“~”),整个“whoami”/“getuid”混乱可以通过使用来避免:
char *buffer = readFile("locate ~/.example");
您仍然可能需要 trim 关闭尾随换行符 and/or CR 字符,也许是:
strtok(buffer,"\r\n\t ");
或者更好,正如@chqrlie 在下面建议的那样。
我正在尝试编写一个程序来检查 /home/user 目录 下是否存在某个位置。为此,我必须使用 whoami
命令获取用户名并将其输出添加到缓冲区以使用 locate
命令。
然而,即使 snprintf
读取了 whoami
命令,它也没有读取其余部分。我进行了几次搜索,得出的结果是 NULL
可能不会在字符串末尾终止。然而,我找不到如何手动终止它。我不确定是什么问题,所以,我在这里。
下面是更好地演示我的问题的代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <string.h>
char *readFile(char *);
bool check();
bool check() {
char path[200] = { 0 };
snprintf(path, 200, "/home/%s/.example", readFile("whoami"));
char lll[300] = { 0 };
snprintf(lll, 300, "locate %s", path);
char *buffer = readFile(lll);
if (strcmp(buffer, path) == 0) {
return true;
} else {
return false;
}
}
char *readFile(char cmd[200]) {
char cmd1[99999] = { 0 };
system("touch cmd");
snprintf(cmd1, 99999, "%s >> cmd", cmd);
system(cmd1);
FILE *f = fopen("cmd", "rt");
assert(f);
fseek(f, 0, SEEK_END);
long length = ftell(f);
fseek(f, 0, SEEK_SET);
char *buffer = (char *)malloc(length + 1);
buffer[length] = '[=10=]';
fread(buffer, 1, length, f);
fclose(f);
system("rm cmd");
return buffer;
}
int main() {
int x = check();
if (x == 1)
printf("There is a location like that");
else
printf("There isn't");
return 0;
}
whoami
命令打印出当前用户的名称,以换行符结束。将文件 cmd
读回 buffer
将包含相同的换行符。
path
字符串将是 "/home/USERNAME\n/.example"
。试图执行
locate /home/USERNAME\n/.example
可能会混淆 system
函数。
解决方案应该是去除 readFile
中的最后一个换行符。
您的 readFile
函数存在一些问题:
该名称具有误导性,应为
runCommand
或类似名称。您将命令输出附加到
cmd
文件。如果cmd
文件在您 运行 您的程序之前存在,这将导致意外结果。你应该改为写:snprintf(cmd1, 99999, "%s > cmd", cmd);
命令输出可能有尾随换行符。你应该 trim 输出。
这是修改后的版本:
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *readFile(const char *cmd) {
/* construct the command */
size_t size = 4 + strlen(cmd) + 1;
char *cmd1 = malloc(size);
assert(cmd1);
snprintf(cmd1, size, "%s > cmd", cmd);
/* run the command */
system(cmd1);
free(cmd1);
/* read the output file */
FILE *f = fopen("cmd", "rt");
assert(f);
fseek(f, 0, SEEK_END);
long length = ftell(f);
fseek(f, 0, SEEK_SET);
char *buffer = malloc(length + 1);
buffer[length] = '[=11=]';
fread(buffer, 1, length, f);
fclose(f);
unlink("cmd");
/* trim trailing white space from the output */
while (length > 0 && isspace((unsigned char)buffer[length - 1])) {
buffer[--length] = '[=11=]';
}
/* trim leading white space from the output */
size_t i = 0;
while (isspace((unsigned char)buffer[i]) {
i++;
}
if (i > 0) {
memmove(buffer, buffer + i, length - i + 1);
}
return buffer;
}
因为 Linux 有一个你的主目录的快捷方式(“~”),整个“whoami”/“getuid”混乱可以通过使用来避免:
char *buffer = readFile("locate ~/.example");
您仍然可能需要 trim 关闭尾随换行符 and/or CR 字符,也许是:
strtok(buffer,"\r\n\t ");
或者更好,正如@chqrlie 在下面建议的那样。