【问题标题】:Inserting and deleting spaces in a text array using C使用 C 在文本数组中插入和删除空格
【发布时间】:2015-10-05 20:04:32
【问题描述】:

我已经设法从程序中创建了以下输出:

7.86 ( 8Hm,),  6.82 ( 4Hm,),12.1 ( 1Hs,).

我想根据我指向的字符添加空格或删除空格。 sscanf 会允许你这样做吗?

我只是想知道在此文本中插入和删除空格的最简单方法是什么。例如,我想删除( 和'num' 之间的空格,例如8,但在H 和'letter' 之间提供一个空格,例如m。到目前为止,我的代码看起来像这样:

typedef struct node {
    int i;
    char array[SIZE];
    struct node* link;
} node;

node* format(void)
{      
    int count = 0;
    int size = list_size(data, sizeof(data)) / 4;

    for (node* ptr = head; ptr != NULL; ptr = ptr->link)
    {
        int i;
        int j; 

        for (i = 0, j = 0; i < sizeof(ptr->array); i++, j++)
        {             

            if (ptr->array[0] == ' ' && count == 0)
            {                
                count++;
                j--;               
            } 


            else if (ptr->array[i] == ' ' && ptr->array[i-1] == '.')
            {                
                j--;
                ptr->array[i] = ','; 
            }    


            else if (ptr->array[i] == ',' && ptr->array[i-1] == ')')
            {
                if (count == size)
                {                                   
                    ptr->array[i] = '.';
                }
            }        


            ptr->array[j] = ptr->array[i];

        }  

        count++;  


    } 

    return head; 
}

请注意,上面当前是一个大小为 3 的链表,我创建了后者以启用字符“组”的交换,然后以特定方式反转顺序。如果我先将所有内容传回单个数组,格式化会更容易吗?

我们将不胜感激地收到任何提示/建议!

【问题讨论】:

  • 如果没有看到您如何定义构成链表的结构,您的问题几乎是不可能回答的,但假设 node-&gt;array[] 只是一个包含您正在格式化的字符串的字符数组,然后显示列表中包含的字符串的内容(或示例内容)肯定会帮助人们帮助您。您不应该期望人们必须对您的字符串进行逆向工程才能帮助格式化。
  • 没错。首先正确格式化。
  • 是的,节点如下:

标签: c arrays linked-list


【解决方案1】:

最简单的方法是使用sscanf 正确解析字符串,然后将其打印到另一个字符串。以您正在执行的方式手动解析字符串不会给您带来明显的速度/内存增益,并且只会添加大量代码。

示例

#include<stdio.h>

int main(){
    char str[]= "7.86 ( 8Hm,),  6.82 ( 4Hm,),12.1 ( 1Hs,).";

    float f1, f2, f3;
    int i1, i2, i3;

    sscanf(str, "%f ( %dHm,),  %f ( %dHm,),%f ( %dHs,).", &f1, &i1, &f2, &i2, &f3, &i3);
    printf("%f ( %dHm,),  %f ( %dHm,),%f ( %dHs,).\n", f1, i1, f2, i2, f3, i3);

    return 0;
}

scanf 函数功能强大,如您所见,您可以使用它们来解析格式化字符串。当您运行此示例中的代码时,它会打印以下内容:

7.860000 ( 8Hm,),  6.820000 ( 4Hm,),12.100000 ( 1Hs,).

它的工作方式是scanf 可以忽略字符。所以它读取第一个浮点数,然后忽略空格,忽略括号,读取 int,忽略 Hm 等等。

我的printf 正在以与输入相同的方式格式化字符串。您可以对其进行调整以满足您的要求。您还应该搜索并限制十进制数字。但基本思想是,你从字符串中获取你需要的数据,然后你可以按照你想要的方式打印这些数据。

【讨论】:

  • 嗨,对不起,节点是 typedef struct node {int i;字符数组[大小];结构节点*链接;}节点;
  • 另外,我想根据我指向的字符添加空格或删除空格。 sscanf 会允许你这样做吗?
  • @Matthew2015 请将这些 cmets 中的信息添加到 问题
  • 特别是对于复杂格式,在使用读取的值之前检查sscanf() 结果总是一个好主意。
  • 要允许在源行中使用不同的间距成功扫描,建议"%f (%d Hm , ) ,%f (%d Hm , ) ,%f (%d Hs , ) ."。在每个文本标记之前添加一个空格。 %d%f 之前不需要空格。
【解决方案2】:

尽最大努力了解您当前在 ptr-array 中拥有的内容,然后如何完成重新格式化,您似乎想要这样做 in-place 只需更新 ptr-&gt;array 以保持更新的格式化字符串,然后您可以构建一个格式正确的缓冲区来替换当前的ptr-&gt;array

注意: 更好的解决方案是将 ptr-&gt;array 中的值分离为实际的单独值,并将其作为链接列表的一部分,您可以在其中静态声明一个结构数组来保存您的 @ 987654326@ 和 units(这是我对 7.86 (8Hm,) 的最佳猜测。这将允许您以任何需要的方式格式化值,而不是被 array 中的内容所困扰。例如:

#define USIZE 8

typedef struct values {
    double value;
    char[USIZE];
} values;

typedef struct node {
    int i;
    char array[SIZE];
    values *vals;
    struct node* link;
} node;

或者,例如:

typedef struct node {
    int i;
    char array[SIZE];
    values vals[3];
    struct node* link;
} node;

无论如何,您最初的问题是如何重新格式化您现有的ptr-&gt;array 删除'(' 之后的空格并将'8Hm' 分隔为'8H m' 在您的示例数据中:

7.86 ( 8Hm,),  6.82 ( 4Hm,),12.1 ( 1Hs,).

鉴于您正在遍历列表中的每个节点,这种重新格式化可能只会在您收集/存储所有节点后运行一次。一种方法是构造一个以新格式保存array 的新缓冲区,然后用正确格式的buffer 替换新的array

是的,有很多方法可以做到这一点,但如果您的重新格式化标准受到限制,只需使用经过验证的 inch-worm 方法填充新缓冲区并使用指针向下走 array使用所需格式的字符与其他任何东西一样简单和灵活。

下面的示例创建了一个新缓冲区 (buf[SIZE]) 从ptr-&gt;array 复制/替换/删除字符,然后将ptr-&gt;array 替换为buf 的内容。

注意:我没有在任何数据上运行这个,所以你可能需要稍微调整一下逻辑。这只是为了向您展示一种可以使用的方法,并使其尽可能接近您的问题的解决方案(据我所知)。

注意 2:如果您不限于特定的标头,您可以用 isupperislower 中的 ctype.h 替换下面的 大写/小写 条件条件。此外,下面的memcpy 将需要string.h,但如果这是一个问题,可以重写以简单地进行复制。

node* format(void)
{      
    /* for each node in list */
    for (node* ptr = head; ptr != NULL; ptr = ptr->link)
    {
        /* declare a pointer to `ptr->array` and `buf` */
        char *p = ptr->array;
        char *pend = p + SIZE;
        char buf[SIZE] = {0};
        char *bp = buf;

        /* for each char in ptr->array */
        while (p < pend)
        {
            /* if not the first char */
            if (p > ptr->array)
            {
                /* if current char is ' ' */
                if (*p == ' ')
                {
                    /* if previous char is one of the following */
                    if (*(p - 1) == '.') *bp++ = ',';
                    if (*(p - 1) == ')') *bp++ = '.';
                    if (*(p - 1) == '(') { p++; continue; } /* remove ' ' after '(' */
                }

                /* if current is lower case & prior is upper, separate */
                else if (('a' <= *(p - 1) && *(p - 1) <= 'z') && ('A' <= *p && *p <= 'Z'))
                {
                    *bp++ = ' ';
                    *bp++ = *p;
                }
                /* default - copy current to buf */
                else
                    *bp++ = *p;
            }
            p++;    /* advance to next char */
        }
        /* copy formatted string to ptr->array */
        memcpy (ptr->array, buf, SIZE);
    } 

    return head; 
}

注意 3:如果 SIZE 是全局 #define,则将 sizeof (ptr-&gt;array) 替换为 SIZE

【讨论】:

  • p &lt; p + sizeof (ptr-&gt;array) 将始终为真(psizeof 都是非负数),因此 while 将无限运行。
  • 谢谢!接得好。没有什么比针对 p &lt; p + 2; p++; :) 进行测试更棒了
  • 因为它是一个字符串,我喜欢针对NULL进行测试。
  • 但是根据提问者的代码不能保证它是空终止的。这就是没有使用简单的while (*p)... 的全部原因。
猜你喜欢
  • 2021-06-06
  • 2011-07-05
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
  • 2016-02-06
  • 1970-01-01
  • 2018-06-07
相关资源
最近更新 更多