3

我在这里基于 4 个参数构建一个字符串并使用 system() 调用它,但我这样做的方式似乎有点混乱。有没有更正确的方法我应该这样做而不使用所有那些 strcat 和 str1-4?

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

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

    char str1[40] = "sed -n 's/.*\\(";
    char str2[] = "\\)\\(.*\\)\\(";
    char str3[] = "\\).*/\\2/p' ";
    char str4[] = " > ";

    if (argc != 5)
    {
        fprintf (stderr, "Usage %s <LogFile> <token1> <token2> <DumpFile>\n",
                argv[0]);
                exit(EXIT_FAILURE);
    }

    strcat(str1, argv[2]);
    strcat(str1, str2);
    strcat(str1, argv[3]);
    strcat(str1, str3);
    strcat(str1, argv[1]);
    strcat(str1, str4);
    strcat(str1, argv[4]);

    system(str1);

    return 0;
}
4

6 回答 6

8

您的代码的一个问题是您没有检查是否适合 40 个字节的参数。

我可能会使用snprintf

snprintf(str, LENGTH, "sed -n 's/.*\\(%s...", argv[2]...);
于 2012-01-30T19:48:56.183 回答
3

这节省了重复的二次行为strcat()。OTOH,如果你打电话,那会迷失在噪音中system()

char str1[4096];
char str0[] = "sed -n 's/.*\\(";

sprintf(str1, "%s%s%s%s%s%s%s%s", str0, argv[2], str2, argv[3], str3, argv[1], str4, argv[4]);

snprintf()如果你担心缓冲区溢出,你可以使用(你应该这样做;40 个字节str1是不够的;你把 96 留在最后,如char str1[4096];)。您可以检查返回值以查看写入了多少个字符。

于 2012-01-30T19:50:43.623 回答
2

总有sprintf可以让你的生活更简单。确保如果您使用 sptrintf 缓冲区对于结果来说足够大。还有一个更安全的版本snprintf将为您进行边界检查。

于 2012-01-30T19:48:20.137 回答
2

唯一的问题是您可能会遇到缓冲区溢出(如果输入太长)。要修复它,检查字符串的长度(使用strlen),并分配足够的内存来包含您想要的字符串。

分配足够的内存后,您可以使用循环,或者让sprintf工作为您完成。

于 2012-01-30T19:48:29.377 回答
2

str1仅 40 字节长,并且您向其附加了太多数据。很可能会发生堆栈溢出。我会做:

char buffer[1000]; // Choose a reasonable size
snprintf(buffer, sizeof(buffer),
    "sed -n 's/.*\\(%s\\)\\(.*\\)\\(%s\\).*/\\2/p' %s > %s",
    argv[2], argv[3], argv[1], argv[4]);
于 2012-01-30T19:49:55.620 回答
1

如果您希望您的代码处理任意长的参数,那么您将需要使用动态分配字符缓冲区malloc

  1. 创建一个局部变量来计算所需的总长度,并使用重复调用strlen来计算该长度。
  2. 调用malloc记住为空终止符再添加一个字符。
  3. 使用strcpystrcat多次来构建字符串。
  4. 打电话system
  5. 打电话free(或者如果您的进程即将终止,请不要打扰)。
于 2012-01-30T19:50:50.800 回答