0

好的,我知道这可能会被标记为重复,但我到处搜索但无法弄清楚,所以请多多包涵。

首先让我说这是一个家庭作业,所以我不能更改函数参数类型。

此外,我不允许使用任何库(嗯,在进行更改的函数内部)。

第1部分


首先,我将如何做到这一点:

void changeMe(char* s, int size) {
   //Change s to be "Hello, World!"
}

int main(void) {
   char* c;
   changeMe(c, 13);
   printf("%s", c); //Print out "Hello, World!"
}

(作业不需要“Hello,World!”位,但我不需要逻辑帮助,只需更改传递的变量。)

我已经看遍了,大多数答案最终都像这里的这个,它说我需要参数是char** s,或者char*& s为了改变它。

我唯一的选择是假设在传递之前已经为 s 分配了足够的内存吗?例如:

void changeMe(char* s, int size) {
   int i;
   for (i = 0; i < size - 1; i++) s[i] = 'a';
   s[size - 1] = '\0';
}

int main(void) {
   char* c = (char*) malloc(10 * sizeof(char)) ;
   changeMe(c, 10);
   printf("%s", c); //Prints out "aaaaaaaaa"
}

这工作正常,但从malloc(...)声明中删除c不会。

放入函数malloc(...)内部可以在本地工作,但只会在范围内changeMe(...)持续。changeMe

有没有办法改变我的char* c而不假设它在传递给函数之前分配了足够的内存?

第2部分


这几乎与上面的内容完全属于同一类别,因此我将在这里少做解释。

功能:

void split(char* s, char** sub, int max, char sep) {
   //Split string s by sep char, store all substrings found into sub
   //sub will have at most max substrings in it.
}

我不是在寻求帮助编写查找和拆分的char* s逻辑char c。我能做到。我的问题主要和上面一样。我如何分配内存char** sub以便它可以容纳其中的所有子字符串(当然,更改传递的变量)。

例如:

void split(char* s, char** sub, int max, char sep) {
   //-->(Needed) Make sub able to hold max strings.
   //(Not Needed) Logic for splitting s up by sep, creating a substring.
   //-->(Needed) Making sub[i] have memory to hold current substring.
}

int main(void) {
   char* s = "Some String To Use";
   char** subs;
   split(s, subs, 10, ' ');
   //subs should look like this:
   //{"Some", "String", "To", "Use"}
}

我不需要帮助来完成实际工作,我只是对如何传递subssplit(...)让它分配适当的内存和更改感到困惑subs


如果您已经完成了我的问题,感谢您的阅读。

而且,在所有“你尝试过 google”评论进来之前,是的。到目前为止,这里有一些我看过的内容:

(编辑:谢谢,hacks,为我添加超链接。)

同样,如果我是为自己编写这个,我会更改参数(char** s而不是char* s例如),并使用漂亮、有用的函数,如strcpy等,但在这种情况下我不能这样做。任何帮助/输入将不胜感激,在此先感谢大家!

4

4 回答 4

1

第1部分

参数的重点size是让函数changeMe()知道缓冲区的大小。您不需要假设大小,因为通常情况下,这样的函数将按如下方式使用:

int main()
{
    int size;
    char* c;

    // some code to calculate the required size of the buffer in bytes
    size = calculateRequiredSize();

    // allocate the buffer
    c = ( char* )malloc( size );

    changeMe( c, size );
}

但是,针对您的问题,在函数changeMe()中,如果不假设size已经分配了字节的内存缓冲区,就无法更改存储在缓冲区中的数据。

第2部分

此处的逻辑相同,尽管它被分成两部分(双关语)。

只需修改您的示例,您将执行以下操作:

void split(char* s, char** sub, int max, char sep) {

    char*   pCurrent;   // pointer to the beginning of the current substring inside the original string.
    int     lenCurrent; // length of the current substring

    // Making sub[i] have memory to hold current substring.
    int i;
    for ( i = 0; i < max; ++i )
    {
        //(Not Needed) Logic for splitting s up by sep, creating a substring.
        // OK -> I leave it to you.

        sub[i] = (char *)malloc( lenCurrent + 1 );  // use length of the current substring + an extra space for the terminating NULL character

        // I will leave it to you to copy the substring to sub[i]
    }
}

int main(void) {
    char* s = "Some String To Use";
    int max = 10; // Decide the value of max out here.
    char** subs = (char**)malloc( max * sizeof( char* ) );
    // Make subs able to hold max strings.
    split(s, subs, max, ' ');
    //subs should look like this:
    //{"Some", "String", "To", "Use"}
}
于 2013-11-14T08:23:25.097 回答
0

祝你的家庭作业好运!至少你足够诚实地承认你在这里做作业...... :)

问候第 2 部分:

Sub 实际上是一个 char* - 数组(char *sub[max])

所以你需要遍历s,找到在哪里拆分,拆分部分的大小是多少。之后,在 sub[] 数组中分配所需的大小。这样,您将准确分配所需的金额。

另一种解决方案: 如果您不允许使用malloc(),您可以更改 *s 字符串。仔细检查它,并将每次出现的 更改sep'\0'。然后将正确的sub[i]指针指向字符串的开头。这实际上是如何strsep()工作的。

恶魔启动:

假设s"Hello-World-This-Is-Homework"。然后设置sub[0]指向s[0],这是第一部分的开始。一直s到下一个'-'。将其更改为'\0'. 然后指向s[1]的开头"World",然后将下一个更改'-''\0',等等...

问候第 1 部分:

在您告诉我们在第 2 部分中您收到了一个已分配的数组之后,我假设在第 1 部分中该数组也已分配。所以你实际上有char s[size]. 所以看起来你的解决方案是正确的——如果用户传递了错误的元素大小,这是他的错。你无法验证它。

于 2013-11-14T08:15:23.630 回答
0

当您修改作为参数传递给函数的数组(指针)时,您也在调用者中修改它的内容。这是因为 C 通过复制参数来工作,但在这种情况下,它复制的是指针,而不是它指向的值。因此,您需要在函数中修改指针指向的值,而不必以特殊方式传递指针。但是,请注意,为了能够访问和修改内存,它必须在调用函数中分配。这就是为什么你不能删除 malloc。

于 2013-11-14T08:20:32.757 回答
0

第1部分

如果您的函数原型 changeMe(char* s, int size) 无法更改,那么您唯一的选择是为函数提供足够大的缓冲区以容纳新字符串,

void changeMe( char* s, int size )
{
  if ( s != NULL && s > 0 )
  {
    char* p = strncpy( s, "Hello, World", size-1 ); // assuming size includes \0
    if ( p != NULL )
    {
      p[size - 1] = '\0'; // make sure it is 0 terminated.
    }
  }
}

您需要“char** s”作为参数来更改大小的原因是 char* s 意味着地址是按值传递给函数的,即原始地址的副本类似于如果您传递了一个诠释:

void foo(int n) // n is a copy of the original value
{
  n = 1; // modifying the copy
}

n 的值不会在 foo 之外改变,但如果你写

void foo(int* n) // n is now pointing to the original value
{
  *n = 1; // changing what n points to i.e. the original value
}  

当涉及到字符串时,原理相同,只是多了一层间接性

void foo(char* s)
{
  s = "hello"; // just temporarily changes what the copy s points to, not the original
}

void foo(char** s)
{
  *s = malloc(10); // changes what the original s points to
}

第2部分

提示:查看 realloc(),该函数作为 malloc 工作,但动态扩展内存块

于 2013-11-14T08:30:49.580 回答