【问题标题】:Delete/substitute two or more consecutive chars in array of chars删除/替换字符数组中的两个或多个连续字符
【发布时间】:2015-10-29 01:06:13
【问题描述】:

我正在学习 C 并且必须编写一个程序:

  • 从标准输入读取一定数量的字符并将它们存储在一个数组中;
  • 用任意两个或多个连续空格 (' ') 替换一个;
  • 写回数组。

到目前为止,我已经完成了以下工作:

#include <stdio.h>
#define DIM 100

int main(int argc, char **argv)
{
    char mainArray [DIM]={'\0'};
    int auxArray [DIM];
    int i, m, n, c, l;

    printf("Enter a string containing two or more consecutive spaces:\n");

/* Read string from stdin */
    do
    {
        mainArray[i]=getchar();
        ++i;
    } while ((mainArray[i-1] != '\n') && (i < DIM-1));

/* Place the string terminator '\0' */
    if (i < DIM)
        mainArray[i]='\0';
    else
        mainArray[DIM-1]='\0';

    l=i;

/* My substitution algorithm */
    for (i=0 ; mainArray[i] != '\0' ; ++i)
    {
        if (mainArray[i] == ' ')
        {
            if (mainArray[i] == mainArray[i+1])
            {
                auxArray[m]=i;
                ++m;
            }
        }
    }

    for (i=0 ; i < m ; ++i)
    {
        for (c=auxArray[i] ; c < l-1 ; ++c)
            mainArray[n]=mainArray[n+1];
    }

/* Display the corrected string */
    for (i=0 ; mainArray[i] != '\0' ; ++i)
        printf("%c", mainArray[i]);

    return 0;
}

例如,输入字符串“a_long_time_ago___in_a_galaxy__far____,_far_away..”将产生“a_long_time_ago_in_a_galaxy_far_,_far_away..”

对于替换算法,我认为一种可能是存储多余的空格位置,然后通过辅助数组删除主数组中的空格。

我确定我犯了一些业余错误。另外,您认为如何优化代码?

提前谢谢你。

【问题讨论】:

  • 使用 2 个指针,使用一个指针(可能继续使用 for(i))遍历整个数组,然后复制到同一数组的另一个位置(调用此指针 J 并从 0 开始,起初它会复制自己)并有一个标志表明你找到了一个空间并在你找到另一个空间并且设置了标志时复制了它(第一个空间),只需“继续”i,但不要增加 j,直到找到复制到 *j 的非空格并继续遍历数组...不要忘记在最后一个 *j 位置添加空终止符...
  • @Ryu 谢谢!我也会尝试你建议的方法。
  • 尝试习惯于使用for 对使用迭代变量的循环进行编码,并在其第一个表达式中声明迭代变量(带有初始化器)。 “重用”迭代变量是编码错误的平均来源。 (进一步简化似乎可能会丢弃不需要的空格字符而不是将它们写入(有限的)缓冲区 - 所呈现的分配要求否则,如果您无法消除规范的皱纹,最好按照字母进行。)
  • @greybeard :“重用迭代变量”是什么意思?
  • 永远不要在循环之后使用迭代变量,除了使用该值在一个地方处理提前和定期终止:如果您的下一次访问是读取,语言系统不会更好比正在初始化的变量,并且不能指向您丢失的初始化。一般来说,保持范围尽可能小,并且更喜欢暗示性的名称而不是简短的名称。 (在我看来,i (j, k),以及使用 C、pq(、sd) 作为指针,强烈建议使用“迭代变量”。)

标签: c arrays string algorithm substitution


【解决方案1】:

这不是代码审查,但您的代码有几个明显的问题:

mainArray[i]=getchar(); - 你还没有初始化 i,所以你正在写入一些随机内存地址,可能你正在调试模式下编译,其中编译器将变量设置为 0,但一般情况下 - 不要这样做这个

if (i &lt; DIM) - 你不需要它,因为 i after loop 将指向 \n 之后的下一个符号,或者它将等于 DIM-1, so justmainArray[i]='\0';` 是够了

auxArray[m]=i; - m 未初始化

for (i=0 ; i &lt; m ; ++i)我无法理解这个循环的逻辑,尤其是mainArray[n]=mainArray[n+1]; - 你没有改变n。存储空间索引的整个方法是错误的,在您删除至少一个空间序列后 - 数组中的所有索引都变成错误的。

这里有一点不同的版本,只有一个数组:

#include <stdio.h>
#include <string.h>
#define DIM 100

int main(int argc, char **argv)
{
    char mainArray [DIM]={'\0'};
    int i, j, k;

    printf("Enter a string containing two or more consecutive spaces:\n");

    fgets(mainArray, DIM, stdin); // note: last symbols of the array will be \n\0
    mainArray[strlen(mainArray)-1] = '\0'; // trimming \n

    printf("[%s]\n", mainArray);

    for (i=0; mainArray[i] != '\0' ; ++i) {
        if (mainArray[i] == ' ') {
            for (j=(i+1); mainArray[j]==' '; ++j) ; // calculate end of space sequence, j will point to the first non space symbol
            for (k=j; mainArray[k]!='\0'; ++k) // copy rest of string to the position after first space
                mainArray[i+1+(k-j)] = mainArray[k];
            mainArray[i+1+(k-j)] = '\0'; // put null-terminator
        }
    }

    printf("[%s]\n", mainArray);
    return 0;
}

【讨论】:

  • 很好的答案。关于未初始化的变量,这肯定是一个编辑错误,因为我在原始代码中将它们全部设置为 0。对于那个很抱歉。我现在明白为什么当你说在删除至少一个空格序列后 - 数组中的所有索引都变成错误的索引时,循环不起作用。似乎也可以通过使用指针使代码更简单,但我认为应该只使用数组算术来完成这个练习。我处于初学者水平,仍在从事编码思维过程。你很有帮助,谢谢!
【解决方案2】:

这是另一种仅使用 char* 指针的方法:

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

int
main(void)
{
    char *lhs;
    const char *rhs;
    int chr;
    char mainArray[500];

    fgets(mainArray,sizeof(mainArray),stdin);

    lhs = strchr(mainArray,'\n');
    if (lhs != NULL)
        *lhs = 0;

    printf("INP: '%s'\n",mainArray);

    lhs = mainArray;
    rhs = mainArray;

    for (chr = *rhs++;  chr != 0;  chr = *rhs++) {
        *lhs++ = chr;
        if (chr != ' ')
            continue;

        for (chr = *rhs;  chr != 0;  chr = *++rhs) {
            if (chr != ' ')
                break;
        }
    }

    *lhs = 0;

    printf("OUT: '%s'\n",mainArray);

    return 0;
}

更新:这是上面重新编码的使用索引。请注意,它更冗长,没有好的效果。但是,逻辑仍然很简单。这是要点之一。为了将来参考,重要的是要让你的逻辑“尽可能简单——而不是更简单”,因为随着项目的增长,效果会被放大,无论好坏。

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

int
main(void)
{
    char *cp;
    int lhs;
    int rhs;
    int chr;
    char mainArray[500];

    fgets(mainArray,sizeof(mainArray),stdin);

    cp = strchr(mainArray,'\n');
    if (cp != NULL)
        *cp = 0;

    printf("INP: '%s'\n",mainArray);

    lhs = 0;
    rhs = 0;

    for (chr = mainArray[rhs++];  chr != 0;  chr = mainArray[rhs++]) {
        mainArray[lhs++] = chr;
        if (chr != ' ')
            continue;

        for (chr = mainArray[rhs];  chr != 0;  chr = mainArray[++rhs]) {
            if (chr != ' ')
                break;
        }
    }

    mainArray[lhs] = 0;

    printf("OUT: '%s'\n",mainArray);

    return 0;
}

另外,请在此处查看我的答案:Issue implementing dynamic array of structures

这是关于结构数组[可能看起来有点高级],但只是假设partition 类型是typedef int partitiontypedef char partition。另外,请参阅关于 int 数组和指针可互换的最后一部分。

【讨论】:

  • 感谢您的替代方案,它工作得很好。我会记住它以供将来参考。在这个练习中,它应该只使用数组算术,下一步将使用指针。谢谢
  • 再次感谢您@Craig,由于分配,我很快就会深入研究指针和动态内存,您提供的示例将对我有很大帮助。
猜你喜欢
  • 2022-01-01
  • 2010-10-23
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-14
  • 2011-05-13
相关资源
最近更新 更多