2

这里我有一个字符串:

*line = "123 567 890  ";

最后有2个空格。我希望将这 2 个空格添加到 3 的末尾和 7 的末尾,使其如下所示:

"123  567  890"

我试图实现以下步骤:

  1. 按单词列表(字符串数组)将字符串解析为单词。从上游函数中,我将获得变量 word_count、*line 和保持的值。
  2. 最后用空格连接它们。
  3. 分配地添加空间,从左到右优先。
  4. 将所有内容连接在一起以使其成为新的*行。

Word_count 是 *line 中的单词数,remain 是剩余的空格数。

这是我的错误代码的一部分:

int add_space(char *line, int remain, int word_count)
{
    if (remain == 0.0)
        return 0; // Don't need to operate.

    int ret;
    char arr[word_count][line_width];
    memset(arr, 0, word_count * line_width * sizeof(char));

    char *blank = calloc(line_width, sizeof(char));
    if (blank == NULL)
    {
        fprintf(stderr, "calloc for arr error!\n");
        return -1;
    }

    for (int i = 0; i < word_count; i++)
    {
        ret = sscanf(line, "%s", arr[i]); // gdb shows somehow it won't read in.
        if (ret != 1)
        {
            fprintf(stderr, "Error occured!\n");
            return -1;
        }
        arr[i] = strcat(arr[i], " "); // won't compile.
    }

    size_t spaces = remain / (word_count * 1.0);
    memset(blank, ' ', spaces + 1);
    for (int i = 0; i < word_count - 1; i++)
    {
        arr[0] = strcat(arr[i], blank); // won't compile.
    }

    memset(blank, ' ', spaces);
    arr[word_count-1] = strcat(arr[word_count-1], blank);

    for (int i = 1; i < word_count; i++)
    {
        arr[0] = strcat(arr[0], arr[i]);
    }

    free(blank);
    return 0;
}

它不工作,你能帮我找到不工作的部分并修复它们吗?谢谢你们。

4

3 回答 3

4

这是一个替代建议 - 可能更快,并且使用更少的内存。

首先 - 请注意,您返回的行将与您开始的行大小相同 - 所以我们只需要移动单词并添加空格。据我所知,您当前的代码似乎没有尝试实际返回固定字符串……</p>

从字符串的末尾开始计算“额外空格”的数量(我认为这是你的remain值)。现在向后遍历字符串,直到找到最后一个单词的开头,然后移动它。

我写了一个示例 - 使用一些调试语句使发生的事情更加明显,并在添加空格时包括 ' ' 而不是 ' '。这更清楚地向您展示了它在做什么(尽管很明显,当您使用此代码时,您会希望将 ' ' 替换为 ' ')。

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

int distributeSpaces(char* s, int wordCount, int spaceCount);

int main(void) {
  char *myString = "There is a house in New Orleans       ";
  char *sCopy;
  sCopy = malloc(strlen(myString)+1);
  strcpy(sCopy, myString);
  printf("Initial string: '%s'\n", myString);
  distributeSpaces(sCopy, 7, 7);
  printf("\nString is now '%s'\n", sCopy);
  return 0;
}

int distributeSpaces(char* s, int wordCount, int spaceCount) {
  int ii, length;
  int wordLength, wordEnd;
  int spaceLeft = spaceCount + 1;
  length = strlen(s);
  printf("string is %d characters long\n", length);
  wordEnd = length - spaceLeft - 1;
  wordLength = 0;
  for(ii = length - spaceLeft - 1; ii > 0; ii--) {
    wordLength++;
    if(s[ii] == ' ') {
      // printf("found space - moving %d characters from %d to %d\n", wordLength, ii, ii+spaceLeft);
      printf("before memmove, string is '%s'\n", s);
      memmove(&s[ii+spaceLeft], &s[ii+1], wordLength);
      printf("after memmove, string is now '%s'\n", s);
      memset(&s[ii], '*', spaceLeft);
      printf("after memset, string is now '%s'\n", s);
      spaceLeft -= spaceLeft / wordCount--;
      // printf("space left is now %d\n", spaceLeft);
      wordLength = 0;
      ii--;
    }
  }
  return 0;
}

输出:

Initial string: 'There is a house in New Orleans       '
string is 38 characters long
before memmove, string is 'There is a house in New Orleans       '
after memmove, string is now 'There is a house in New OrleansOrleans'
after memset, string is now 'There is a house in New********Orleans'
before memmove, string is 'There is a house in New********Orleans'
after memmove, string is now 'There is a house in New***New**Orleans'
after memset, string is now 'There is a house in*******New**Orleans'
before memmove, string is 'There is a house in*******New**Orleans'
after memmove, string is now 'There is a house in***in**New**Orleans'
after memset, string is now 'There is a house******in**New**Orleans'
before memmove, string is 'There is a house******in**New**Orleans'
after memmove, string is now 'There is a houshouse**in**New**Orleans'
after memset, string is now 'There is a*****house**in**New**Orleans'
before memmove, string is 'There is a*****house**in**New**Orleans'
after memmove, string is now 'There is a**a**house**in**New**Orleans'
after memset, string is now 'There is****a**house**in**New**Orleans'
before memmove, string is 'There is****a**house**in**New**Orleans'
after memmove, string is now 'There isis**a**house**in**New**Orleans'
after memset, string is now 'There***is**a**house**in**New**Orleans'

String is now 'There***is**a**house**in**New**Orleans'

我想这就是你所追求的。

于 2013-11-03T03:41:34.067 回答
3

[编辑]完整代码添加到底部,对原始片段进行更正

那么,据我所知,您的愿望是采用一定长度的现有行,并将其重写为与原始行长度相同的新行,但尽可能均匀地填充空格,最后一个单词后没有空格: 例如:

“This is my original sentence”(末尾四个空格 - 字符串长度为 32)

|T|h|i|s| |我|s| |m|y| |o|r|i|g|i|n|a|l| |s|e|n|t|e|n|c|e| | | | |

您想重新分配空间以保留原始长度 32:

|T|h|i|s| | |我|s| | |m|y| | |o|r|i|g|i|n|a|l| | |s|e|n|t|e|n|c|e|。

下面应该提供一组可以在代码中实现的步骤,以在保持其原始长度的情况下将单词均匀分布在一行中。

首先,存储原始行长:

int origLen = strlen(line);

第一次使用strtok()空格" "作为分隔符解析字符串,目的是收集以下内容:

1) 字数
2) 所有字的累计长度

char *buf;
char temp[80];    
char lineKeep[80];
int accumLen=0;
int wordCount=0;
int numSpaces;

strcpy(lineKeep, line);

buf = strtok(lineKeep, " ");
while(buf)
{
    strcpy(temp, buf);
    accumLen += strlen(temp)+1;//+1 because each word includes one following space
    wordCount++;
    buf = strtok(NULL, " ");
}
accumLen--; //remove last space

现在您可以重复解析,但这次您获得了在解析字符串时重新构造字符串所需的信息:

numSpaces = (origLen - accumLen)+1;//determine number of trailing spaces after last word
                                   //+1 to compensate for space at end of last word.

//parse line, place words and extra spaces  
int spcToAdd;  //number spaces added to every word except last
int extraSpc;  //remainder spaces to distribute  

spcToAdd = numSpaces/(wordCount - 1);
extraSpc = numSpaces%(wordCount - 1);

memset(lineKeep, 0, 80);

buf = strtok(line, " ");
while(buf)
{
    strcat(lineKeep, buf);
    for(i=0;i<spcToAdd;i++) strcat(lineKeep, " ");
    if(extraSpc > 0) strcat(lineKeep, " "), extraSpc--;
    buf = strtok(NULL, " ");
}

那应该这样做。

[编辑]
完整代码,对原始片段进行更正:

#include <ansi_c.h>
int main(void)
{
    char line[]="this is my original line      ";
    char *buf;
    char temp[80];    
    char lineKeep[80];
    int accumLen=0;
    int wordCount=0, count;
    int numSpaces;
    int i;
    int origLen = strlen(line);

    strcpy(lineKeep, line);
    printf("Original with \"*\" to demark spaces :*%s*\n", lineKeep);
    buf = strtok(lineKeep, " ");
    while(buf)
    {
        strcpy(temp, buf);
        accumLen += strlen(temp)+1;//+1 because each word includes one following space
        wordCount++;
        buf = strtok(NULL, " ");
    }
    accumLen--; //remove last space

    //second part
    numSpaces = (origLen - accumLen);//determine number of trailing spaces after last word
                                       //+1 to compensate for space at end of last word.
    //parse line, place words and extra spaces  
    int spcToAdd;  //number spaces added to every word except last
    int extraSpc;  //remainder spaces to distribute  

    spcToAdd = numSpaces/(wordCount - 1); //Add one extra space
    extraSpc = numSpaces%(wordCount - 1); //while they last add additional space

    memset(lineKeep, 0, 80);

    count = 0;
    buf = strtok(line, " ");
    while(buf)
    {
        count++;
        strcat(lineKeep, buf);
        if(count < wordCount)
        {
            strcat(lineKeep, " "); //normally occuring space
            for(i=0;i<spcToAdd;i++) strcat(lineKeep, " ");
            if(extraSpc > 0) strcat(lineKeep, " "), extraSpc--;
        }
        buf = strtok(NULL, " ");
    }
    lineKeep[strlen(lineKeep)]=0;
    printf("modified with \"*\" to demark spaces :*%s*\n", lineKeep);
    getchar();
    return 0;
}

此代码的结果图像:

在此处输入图像描述

[编辑] OP 带有注释的原始代码和一些编辑(未完全调试)

int add_space(char *line, int remain, int word_count)
{
    int line_width;  //added

    if (remain == 0.0)
        return 0; // Don't need to operate.

    line_width = strlen(line);

    int ret;
    char arr[word_count][line_width]; //line width not originally defined, 
    memset(arr, 0, word_count * line_width * sizeof(char));

    char *blank = calloc(line_width, sizeof(char));
    if (blank == NULL)
    {
        fprintf(stderr, "calloc for arr error!\n");
        return -1;
    }

    for (int i = 0; i < word_count; i++)
    {
        ret = sscanf(line, "%s", arr[i]); // gdb shows somehow it won't read in.
        if (ret != 1)                     // each time this loops around, "this" is placed into arr[i];
        {                                 // "line" is not changing, strtok will traverse line
            fprintf(stderr, "Error occured!\n");
            return -1;
        }
        //arr[i] = strcat(arr[i], " ");      // won't compile.
        strcpy(arr[i],strcat(arr[i], " ")); // assignment of char array to char array uses strcpy, or sprintf, et. al.
        //each loop now adds " " -> "this " 
                                            // Note: you can assign char to char using =, but not char arrays
    }
    size_t spaces = remain / (word_count * 1.0); //size_t == uint, mult by float is set back into uint.
    memset(blank, ' ', spaces + 1);
    for (int i = 0; i < word_count - 1; i++)
    {
        //arr[0] = strcat(arr[i], blank);     // won't compile.
        strcpy(arr[i],strcat(arr[i], blank)); // Same as above. and index of arr[] should be i
    }

    memset(blank, ' ', spaces);
    //arr[word_count-1] = strcat(arr[word_count-1], blank); //same
    strcpy(arr[word_count-1],strcat(arr[word_count-1], blank));  //at this point, each arr[i] 
                                                                 //contains "test   \0" (3 spaces and NULL)
    for (int i = 1; i < word_count; i++)
    {
        //arr[0] = strcat(arr[0], arr[i]); //same
        strcpy(arr[0], strcat(arr[0], arr[i])); 
    } //at this point arr[0] contains "test   test   test   test   t"
      //ran out of room, note there is no NULL terminator '\0' at end.
    free(blank);
    return 0;
}
于 2013-11-03T03:38:17.220 回答
0

这是一个二维字符数组

char arr[word_count][line_width];

您需要一个 char * (字符指针)数组。

char *arr[word_count];

你分配内存的方式也行不通。

像这样的东西

for(int index=0;index<work_count;index++)
  arr[index] = malloc(line_width*sizeof(char)];

不要忘记在程序结束时释放,否则会发生内存泄漏。

于 2013-11-03T02:49:16.750 回答