cadenas de punteros

to copy at the correct place but doesn't stop after the count is reached. I thought my code should work as follows

char har *orig, int start, int count, char *final);

int main(void)
{
    const char source[] = "one two three";
    char result[] = "123456789012345678";

    printf("%s\n",GetSubstring(source, 4, 3, result));

    return 0;
}

char r *orig, int start, int count, char *final)
{    
    char *temp = (char *)orig;

    final = temp;


   }

    for ( ; *temp && (count > 0) ; count--)
    {
    rn final;
}

preguntado el 31 de julio de 12 a las 13:07

I'm having a very hard time following what you're doing here; this is a very simple thing to do but you've made it very complicated. The one thing that really confuses me is the "final = temp" line. Presumably, the parameter final holds the destination for the copied string, but you've moved it to point to the original string, so copying any characters will result in some part of the original string being overwritten. I really don't know why you're doing that, so it's hard to recommend any specific changes. -

In contrast, Microsoft's implementation of strncpy() -- a standard library function that does basically what you're doing here -- is four lines, one of which is return and one of which is continue. -

if i don't do temp = final the string outputs char result [] 56789012345678, with the temp = final my output is two three, though i though it should just print 'two' and then the count should be reached -

@Ernest: "I really don't know why you're doing that" I hate to be so blunt, but, hey, that's where the error is. That was the whole point of this question: to fix it, to find the error. You shouldn't be confused, not if you've been here a while (and you tienen). Reading inexperienced programmers' minds is pretty much in the job definition here. -

6 Respuestas

  1. El Primer for loop doesn't check if temp array exists (how would it check for existence of an allocated memory without asking memory manager in some way?!). The temp is merely a pointer. What you're checking for is that the orig string doesn't have a zero within the first start bytes. That's OK, perhaps' that's what you meant by "existence".

  2. Your intention is to copy from orig a final, yet you reset final a orig. That's where your error is. You must remove that line and it fixes the problem.

  3. No es necesario crear el temp pointer, you can use the orig pointer. You're free to modify it -- remember, function arguments are in effects local variables. Function arguments in C are pass-by-value, you implement pass-by-reference by passing pointers (which are values!) to data.

I should add perhaps that the premise of this function is somewhat broken. It "works", but it's not what one might reasonably expect. Notably:

  1. There's no indication that the source string was shorter than start.

  2. There's no indication that the source string was shorter than start + count.

    Perhaps those are OK, but in cases where those conditions could be an error, it should be possible for the user of the function to get an indication of it. The caller would know what's expected and what's not, so the caller can determine it if only you'd provide some feedback to the caller.

  3. You're returning the position that's one past the end of the output -- past the zero-termination. That's not very convenient. If one were to use the returned value to concatenate a subsequent string, it'd have to be decremented by one first.

Below is the fixed code, with sanely named variables.

char *GetSub(const char *src, int start, int count, char *dst)
{
    for ( ; *src && (start > 0) ; start--)
    {
        src++; /* Note: *src++ works too, but is pointless */
    }

    for ( ; *src && (count > 0) ; count--)
    {
        *dst++ = *src++;
    }

    *dst++ = 0;
    return dst; /* Notice: This returns a pointer to the end of the
                memory block you just wrote. Is this intentional? */
}

Respondido el 20 de junio de 20 a las 10:06

While I agree that reusing count y start for the counters 'appears' to save an automatic variable, an optimizing compiler would figure this out on its own. the missing initializer for the fors and the use of start-- y count-- make this a little hard to read. Check out the version I wrote in my answer to know what I mean. - ArjunShankar

By the way, what's with return dst after incrementing it so many times (it might actually have been incremented past the destination array's width)? May I hazard a joke about idiomatic C, and how you shouldn't be trying to answer? ;) - ArjunShankar

I think that leveraging pass-by-value semantics of C is the sane way to go in short functions. When a function gets long, it sure helps to have locally declared C99-style loop variables to make the code easy to comprehend. In a short function -- why bother. Of course I agree that the design of this function as written is a bit obscene, but if that's what was called for then, hey, I'm OK with it ;) I know that modern compilers likely won't care any less about extra local variables that are simply copies of arguments. Probably initializer-less for is bad style, though. - Kuba no se ha olvidado de Monica

Anyway, the point was to fix the asker's function to get it to work as presumably intended. All it took was to remove one erroneous line. That was what the asker was for. - Kuba no se ha olvidado de Monica

Maybe you should put a comment on the last line to make it clear that you're not returning a pointer to the start of the destination buffer. It's almost certainly an error, so I think calling it 'fixed code' is misleading. - Diana

Existen Varios problems in what you have written. Let's enumerate:

  1. char *temp = (char *)orig; - You're assigning a const char * (you promise not to modify) to a char * (you break that promise). Wrong thing to be doing.

  2. final = temp. No this does not make the empresas de confitería final (the copy held by the caller) change at all. It achieves nothing. It changes sus (function's) copy of final to point to the same place that temp está apuntando.

  3. *temp++; - There's no point de-referencing it if you're not going to use it. Incrementing it of course, is correct [see comment thread with KubaOber below].

  4. final++ = *temp++; - This is just confusing to read.

  5. *final++ = 0; return final; - You're setting the value at the address final to '0'. Then you're incrementing it (to point to somewhere in space, maybe towards a black hole). Then returning that pointer. Which is also wrong.

Lo que tú democracia should do is to wrap strncpy de una manera conveniente

But if you insist to write your own, you'd probably want your function to be something as simple as:

char *GetSub(const char *orig, int start, int count, char *final)
{    
  int i;

  for (i = 0; i < count; i++)
    {
      final[i] = orig[i+start];

      if (final[i] == '\0')
        break;
    }
  final[i] = '\0';

  return final; /* Yes, we just return what we got.  */
}

Respondido 31 Jul 12, 14:07

Your #3 is a wrong assessment. You're commenting on idiomatic C code like it was alien to you -- perhaps you shouldn't be? *temp++ is dereferencing the pointer, and incrementing it algún tiempo después the dereference. That's all. - Kuba no se ha olvidado de Monica

Okay. It does the reverse. It's an error and I'm going to fix it. - ArjunShankar

@KubaOber - The judgement that C is alien to me might be a bit harsh though. - ArjunShankar

I can only judge by the comment. There's nothing wrong with that line that you commented on. It's an obvious idiomatic C construct, used correctly in the asker's code. - Kuba no se ha olvidado de Monica

@ArjunShankar, actually, the deferencing part is completely unnecessary. - Diana

El problema está en la siguiente línea:

final = temp;

Remove it, and the problem should be resolved.

Respondido 31 Jul 12, 14:07

+1 for a 1 line fix. Although, I hope the OP considers a clean rewrite or even wraps strncpy. - ArjunShankar

char *a="abcdefgh";

i want string "cde" to be copied into another.

index i got is 3(your start).

char *temp=malloc(3*sizeof(char))
strncpy(temp,a+3,3);

¿Esto es lo que necesitas?

Respondido 31 Jul 12, 13:07

no, i have to make a custom copy string with the function I used. Im just trying to understand where my logic breaks down - blitzeus

cambiar su GetSubfunción:

char *GetSub(const char *orig, int start, int count, char *final)
{
    char *temp = (char *)orig;

    // with original final = temp and final++ you loose final valid pointer
    char *final2 = final;


    for ( ; *temp && (start > 0) ; )
    {
        start--;

        // you don't need to dereference temp
        temp++;
    }

    for ( ; *temp && (count > 0) ; count--)
    {
        *final2++ = *temp++;
    }

    *final2 = 0;

    // return a valid pointer
    return final;
}

Respondido 31 Jul 12, 13:07

Heaven help the poor soul who sees a function with local variables called final y final2. All that's to this code is that there is a source and a destination. All this orig, final naming is counterproductive and poor style. - Kuba no se ha olvidado de Monica

@KubaOber, you're right about the bad variable naming, but most of the variable names were defined by the asker. Of course, I agree that 'final2' is a bad name for the variable. However, I think this answer is the most direct one because it explicitly addresses the problem without getting distracted by secondary problems with the code. - Diana

you have some mistakes on your code :

char *GetSub(const char *orig, int start, int count, char *final)
{
    char *temp = (char *)orig;

    //final = temp; /* Why this? */

    for ( ; *temp && (start > 0) ; )
    {
        start--;
        temp++; /* Instead of *temp++ */
    }

    for ( ; *temp && (count > 0) ; count--)
    {
        *final++ = *temp++;
    }

    *(final+count) = '\0';
    return final;
}

Espero que esto ayude.

Respondido 31 Jul 12, 13:07

I think this code is wrong. The last two lines are assuming that 'final' points to the original destination buffer. - Diana

The *(final+count) = '\0' line is incorrect because it is setting a value beyond the end of the destination buffer (according to count) to zero. This could result in a buffer overrun. - Diana

You're also returning a pointer to what should have been the null terminating character. The author probably wanted the function to return the pointer to the destination buffer. - Diana

@Sam : you're wrong! this function return final string which is assumed to be allocated outside this function and have exactly "count" chars length. DOWNVOTE IS ABUSED!! - TOC

Actually, I just double-checked about the buffer overrun issue, and it looks like the null-termination at the end is correct, although it appears to be an accident. Nevertheless, your code indicates that you think 'final' refers to the start of the originally supplied output buffer. The returned value is still probably wrong, too. - Diana

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.