【问题标题】:Replacing a character in a string (char array) with multiple characters in C用C中的多个字符替换字符串(char数组)中的字符
【发布时间】:2014-09-09 02:14:48
【问题描述】:

C 不是托管语言,我已经有一段时间没有使用非托管语言了。我需要创建一个搜索字符数组的代码块,并将所有“2”实例替换为“Ba”。这很简单,除了现在生成的字符串将比原来的大,所以我需要以某种方式解释这一点,我不记得如何做到这一点。

这里是第 4 次尝试,使用指针:

//Move next 150 characters after replacing all 2 with Ba:
    numberread = read(XYZFile, datatoreadWWW, sizeof(datatoreadWWW));
    int y = strlen(datatoreadWWW); //should be 150.
    int additionallength = y;
    i = 0;
    while(i < y) {
      if(datatoreadWWW[i] == '2') {
        additionallength++; //Since we need to replace any '2' with 'Ba', we should add one character for the a.
      }
      i++;
    }
    //And now use additionallength to create the new char array to be placed in WWW, called newstring:
    char newstring[additionallength];
    int j = 0;
    const char *in = datatoreadWWW;
    char *out = newstring;
    while(*in) {
      if (*in == '2') {
    *out++ = 'B';
    *out++ = 'a';
      }
      else {
    *out++ = *in;
      }
      in++;
    }
    *out++ = '\0';

我仍然对此感到困惑/卡住,我将垃圾值写入 WWW 文件,例如“^Q”等。不知道这意味着什么,但它似乎不正确。

编辑: 上面的程序现在似乎可以运行了。问题是,如果有人将这篇文章作为资源阅读,我将 +1 添加到附加长度,但这发生在每次迭代中,所以每有这么多字符,文件中就会有一个额外的空白空间,这是不正确的。无论如何,我认为我们已经了解到,在使用 C 语言时检查指针很重要,因为这是完成此任务的最简单方法。

【问题讨论】:

  • “托管”或“非托管”与此无关。我认为您指的是缺少具有插入操作的标准容器。
  • 'Ba' 是一个 多字节字符常量 ,毕竟它仍然是一个字符。你真正想要的是两个字符,'B''a'。正如你所说,你需要有足够的空间,因为结果会比原来的大。尝试编写一些代码然后发布。
  • K 马特,等一下,我正在努力!
  • C 一种托管语言,它只是开发人员(而不是运行时)进行管理:-)

标签: c arrays string


【解决方案1】:

你可以这样做:

  • 通过将'2's 的数量添加到字符串的strlen 加上一个作为空终止符的数量来计算新数组的长度
  • 使用malloc分配所需数量的chars
  • 循环遍历你的字符串;如果您看到'2',请在输出中添加'B',后跟'a'
  • 否则,将当前字符复制到输出。

注意:既然您的字符串是动态分配的,您需要在使用完毕后调用free

const char* str = ...
int cnt = strlen(str)+1;
for (const char *p = str ; *p ; cnt += (*p++ == '2'))
    ;
char *res = malloc(cnt);
char *out = res;
const char *in = str;
while (*in) {
    if (*in == '2') {
        *out++ = 'B';
        *out++ = 'a';
    } else {
        *out++ = *in;
    }
    in++;
}
*out++ = '\0';

Demo.

【讨论】:

  • 或者,如果您不想循环遍历字符串两次,您可以乐观地预先分配一个仅比输入“稍大”的缓冲区,如果它变成了realloc()ate 它因为它太短了。
  • 这可以在不进行任何分配调用的情况下完成吗?我只是创建了一个新的字符数组,其大小与原始字符数组相同,加上存在的 2 的数量,再加上空终止符的 1。
  • @Musicode 只要在同一个函数中使用结果,它也可以工作。将malloc 行替换为char res[cnt];,代码将继续工作。
  • @Musicode 你忘了最后一行(添加空终止符)。
  • @Musicode 您的最后一次尝试在其他方面也不正确:在我的示例中,您尝试使用单个索引j 而不是两个指针inout。这就是为什么你的代码会跳过一些字符,留下空白。如果您不喜欢指针,请使用索引;全部都是一样。循环结束后,将'\0' 放入您写作索引处的字符中。
【解决方案2】:

许多解决方案过于复杂、冗长无意义且效率低下(例如,strlen 意味着只需要两次扫描时进行三次扫描)。

int newlen = 1;

for (char* p = str; *p; p++)
    newlen += *p == '2' ? 2 : 1;

char newstr[newlen];

for (char *p = str, *q = newstr;; p++)
    if (*p == '2')
    {
        *q++ = 'B';
        *q++ = 'a';
    }
    else if (!(*q++ = *p))
        break;

【讨论】:

  • 我尝试了这种方法,但现在我正在写入的 WWW 文件中出现垃圾值...
  • char newstr[newlen]; 不合法 C,使用 char * newstr = malloc(newlen);
  • @Musicode 也许你写错了,或者你的输入是乱码。我注意到你正在使用read ...这不是一个好主意,也不是NUL-终止输入。使用标准输出。
【解决方案3】:

以下是如何做到这一点的想法:

  • 计算 char 数组中“2”的数量并存储在一个变量中,比如count

  • 创建一个新的 char 数组,比如 new_word您之前的 char 数组的大小加上 count 变量中存储的 2 的数量

  • 从输入单词的末尾开始迭代,将字符存储在new_word 中。每次达到“2”时,插入“a”,然后插入“B”,当然,还要正确更新索引。

【讨论】:

    【解决方案4】:

    你也可以这样试试..

    main()
    {
    char a[]="abcabcabcabcabcabcabc";
    char *p;
    int i=0,c=0;
    
    for(i=0;a[i];i++)
    if(a[i]=='c')
    c++;
    
    printf("c=%d\n",c);
    p=calloc(sizeof(a)+c,1);
    
    for(i=0;a[i];i++)
    {
    static int j=0;
    if(a[i]=='c')
        {
        *(p+j++)='n';
        *(p+j++)='s';
        }
     else
        {
        *(p+j++)=a[i];
        }
       }
       printf("%s\n",p);
      }
    

    【讨论】:

      猜你喜欢
      • 2013-06-27
      • 1970-01-01
      • 1970-01-01
      • 2018-06-30
      • 2014-06-27
      • 1970-01-01
      • 1970-01-01
      • 2019-05-09
      • 1970-01-01
      相关资源
      最近更新 更多