【问题标题】:How to manipulate string properly in C如何在 C 中正确操作字符串
【发布时间】:2013-11-08 04:22:33
【问题描述】:

我还是 C 的新手。我正在执行环境变量任务,但在处理我的字符串时遇到了问题。我想传递一个表示环境变量的变量,如果该字符串与环境键相同,则将具有 ${...} 的值替换为环境值。以下是代码:

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

void replace_env(char *string, char *env)
{
    int y = 0;
    int x = 0;
    int j = 0;
    int i = 0;
    int n = 0;
    int val_length;
    int location2[100];
    char *tmp3[BUFSIZ];
    char env_key[BUFSIZ];
    char env_val[BUFSIZ];
    char env_var[sizeof(env)][BUFSIZ];
    char user_input[BUFSIZ];
    char final_string[BUFSIZ];
    char tmp_key[100][BUFSIZ];

    tmp3[x]=env;
    strncpy(env_var[x],tmp3[x],sizeof(tmp3));

    for(x=0;env_var[y][x] != '=';x++)    //this is to get the environment key
    {
            env_key[x] = env_var[y][x];
    }
    x++;
    for(j=0;env_var[y][j] != '\0';j++)    //this is to get the environment value
    {
            env_val[j]=env_var[y][x];
            x++;
    }
    val_length = strlen(env_val);
    j=0;
    y=0;
    strncpy(user_input,string,sizeof(user_input));

    for(x = 0;user_input[x] !='\0';x++)
    {
     if (user_input[x] =='$')
      {
        x++;
        if(user_input[x] == '{')
         {
           x++;
           y=0;
           while(user_input[x]!='}')
           {
             tmp_key[i][y] = user_input[x];
             x++;
             y++;
           }
          i++;
          }
       }
    }
    tmp_key[i][y]='\0';
    i=0;
    for(x = 0;user_input[x] !='\0';x++)    //I think my problem is starting from here.
    {
     if (user_input[x] !='$')
      {
       final_string[j]=user_input[x];
       j++;
      }
      else
          {
           x++;
           if((user_input[x]== '{')&&(strncmp(tmp_key[i],env_key,sizeof(tmp_key))==0))
           {
            while(user_input[x]!='}')
            {
             x++;
            }
            strcat(final_string,env_val);
            j=j+val_length;
           }
           else    
              {
                final_string[j]=user_input[x];
                j++;
              }
         }
    }
    printf("output result = %s \n",final_string);
}

int main() {
    char s[100];
    sprintf(s, "jack${ABC}zack${DEF}");
    replace_env(s, "ABC=/home/fikrie/Documents");
    replace_env(s, "DEF=/tmp");
    if (strcmp(s, "jack/home/fikrie/Documentszack/tmp")==0) {
            printf("pass\n");
    } else {
            printf("fail\n");
    }
    printf("--------------------------------------------------------\n");

return 0;
}

为了更清楚,下面是结果:

env_var = ABC=/home/fikrie/Documents 
env_key = ABC 
env_val = /home/fikrie/Documents 
input = jack${ABC}zack${DEF} 
after strcat result is = jack/home/fikrie/Documents 
j value is 26 
after strcat result is = jack/home/fikrie/Documentszack/home/fikrie/Documents 
j value is 52 
output result = jack/home/fikrie/Documentszack/home/fikrie/Documents 
env_var = DEF=/tmp 
env_key = DEF 
env_val = /tmp 
input = jack${ABC}zack${DEF} 
output result = jack{ABC}zack{DEF}ocumentszack/home/fikrie/Documents 
fail
--------------------------------------------------------

如您所见,ABC 被发送到 replace_env 函数中。它确实正确替换了 ${ABC},然后是一个字符串 zack。然后问题发生在 ${DEF} 被替换为 ABC 键并且不维护为 ${DEF}

在第二次调用 replace_env 函数期间发送 DEF 时,事情变得更加奇怪。 ABC 和 DEF 都无法识别。更糟糕的是,后面的角色还在。

我的期望是:

For the first call of replace_env:
jack/home/Fikrie/Documentszack${DEF}

For the second call of replace_env:
jack/home/Fikrie/Documentszacl/tmp

after the strcmp passed, the final_string will be cleared again.

非常感谢所有帮助。我不期待答案。我更喜欢知识或指导,而不是茫然地解决它。只需要对我的错误做出明确的解释,因为我已经编辑这段代码将近一个月了,现在一切看起来都很模糊。我知道有一些方法可以使用内存函数、分配等来解决它。但是这个任务是关于字符串操作的。我在 Ubuntu 操作系统上运行它。对不起我的英语不好。

【问题讨论】:

  • 关于strncpy的说明:它不保证在目标字符串的末尾终止'\0'。这不是一个真正的字符串函数,而是被误导性地命名为专用内存复制函数。如果您想要 string 结果,请改用 strncatsnprintf
  • @hyde:如果我没记错的话,strncat 会将字符串复制到目的地而不替换旧字符串,对吧?感谢您推荐 snprintf。在此之后我会考虑更多地使用它。

标签: c string loops


【解决方案1】:

我知道你没有要求这个,但考虑一下。学习 C 字符串函数值得您花时间。

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

void sub(char *s, char *env, char *value) {
        char buf[BUFSIZ], *src = s, *dst = buf;
        int n = strlen(env);
        while(*src) {
                if(strncmp(src, env, n) == 0) {
                        dst += strlen(strcpy(dst, value));
                        src += strlen(env);
                } else {
                        *dst++ = *src++;
                }
        }
        *dst = 0;
        strcpy(s, buf);
}

void replace_env(char *s, char *env) {
        char copy[BUFSIZ], tmp[BUFSIZ];
        strcpy(copy, env);
        char *eq = strchr(copy, '=');
        if(eq == 0) {
                printf("No '=' found in '%s'\n", env);
                return;
        }
        *eq = 0;
        sprintf(tmp, "${%s}", copy);
        sub(s, tmp, eq+1);
}

int main() {
    char s[100];
    sprintf(s, "jack${ABC}zack${DEF}");
    replace_env(s, "ABC=/home/fikrie/Documents");
    replace_env(s, "DEF=/tmp");
    if (strcmp(s, "jack/home/fikrie/Documentszack/tmp")==0) {
            printf("pass\n");
    } else {
            printf("fail\n");
    }
    printf("--------------------------------------------------------\n");
    return 0;
}

【讨论】:

  • 这确实解决了我的问题。但是学习代码和编写代码完全是两件事。我仍然无法使用字符串操作。并不是我不喜欢使用你的代码。我只是不觉得解决我的问题的满足感。尽管如此,我仍然很欣赏你的代码。我会把它作为一个很好的指导。
  • 恕我直言,您的代码过于复杂,因为您正在尝试解决问题。你有一个 87 行的函数,有六个字符缓冲区,其中两个是二维的。函数应该简短、简洁并做一件简单的事情。没有长期研究,没有人能够查看您的功能并弄清楚它的作用。有时,当你发现自己像以前一样深陷困境时,重新开始会更好。将问题分解为简短的函数,一次编写一个,并在执行过程中对其进行测试。也许一个好的下一步是研究我给你的代码,然后把它写出来
  • 抛开并尝试自己重写。如果您遇到困难,请返回我的代码并逐行弄清楚它的作用。您不能在真空中学习代码,每个人都通过尝试和查看示例代码来学习代码。总是试图简化,简化,简化。祝你好运。
  • 是的。我完全同意你的看法。对于一个简单的任务来说太长了。并且为此使用大量内存是不值得的。我意识到我写的是手动处理一个字符串,即逐个字符搜索。您的代码帮助我意识到有一种自动的方法可以做到这一点。感谢您的意见。我会重新开始,希望这次会更清楚。
猜你喜欢
  • 2016-08-21
  • 2012-10-20
  • 2011-06-23
  • 2014-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多