Thread: damn strings

  1. #1
    Registered User
    Join Date
    Jun 2002
    Posts
    4

    Unhappy damn strings

    hi all, i hope u guys can help me, i had a little experience in C but just in math stuff, now i need to handle string but i cant figure it out, i check the forum but i didnt find what im looking for, i now how to create "strings" in C, the problem is when i want to concatenate strings or handle more than one, i want to receive 2 strings and divide them in parts, i receive dates (i know i can make it with integers but my teacher wanted to be with strings, and there are better ways to do this, but my point is why my strings act like that) and then calculate the days between this to dates, when i divide the second string my dummy string fill with trash or values from the other 2 strings, here is the part of my file when i divide the 2 strings

    #include<stdio.h>
    #include<conio.h>
    #include<math.h>
    #include<string.h>
    #include<stdlib.h>
    #include<alloc.h>
    void main(void)
    {

    int dia1,dia2,mes1,mes2,ano1,ano2,dum,i,totdias;
    int mes[12];
    char *fecha1=malloc(sizeof(char)*9);
    char *fecha2=malloc(sizeof(char)*9);
    char *dummy=malloc(sizeof(char)*9);
    mes[0]=0,mes[1]=31,mes[2]=28,mes[3]=31,mes[4]=30,mes[5]=31,mes[6]=30,
    mes[7]=31,mes[8]=31,mes[9]=30,mes[10]=31,mes[11]=30,mes[12]=31;
    totdias=0;
    clrscr();
    gotoxy(5,7);
    printf("Format yyyyymmdd (yearmonthday)");
    gotoxy(5,11);
    printf("First date: ");
    scanf("%s",fecha1);

    strncpy(dummy,fecha1,4);
    ano1=atoi(dummy);
    strncpy(dummy,fecha1,6);
    dum=atoi(dummy);
    mes1=dum-(ano1*100);
    strncpy(dummy,fecha1,8);
    dum=atoi(dummy);
    dia1=dum-((ano1*10000)+(mes1*100));
    gotoxy(5,13);
    printf("Second date: ");
    scanf("%s",fecha2);
    free(dummy); //liberate dummy
    strncpy(dummy,fecha2,4);
    ano2=atoi(dummy);
    strncat(dummy,fecha2,6);
    dum=atoi(dummy);
    mes2=dum-(ano2*100);
    strncat(dummy,fecha2,8);
    dum=atoi(dummy);
    dia2=dum-((ano2*10000)+(mes2*100));
    }

    i hope u can help me out, im programming on turbo c++ 3 on windows xp, thanks a lot.

    Juan

    P.S. Sorry for my bad english

  2. #2
    Me want cookie! Monster's Avatar
    Join Date
    Dec 2001
    Posts
    680
    Some tips:

    1. mes[12]=31;

    This is not going to work because your array is 12 long (0-11)

    2. void main(void)

    This is wrong, use int main(void);

    3. int mes[12];

    You can also fill the array when declaring it:
    int mes[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

    4. char *fecha1=malloc(sizeof(char)*9);

    If you allocate something it's always nice to free the allocated memmory (same for fecha2).
    Why do you use dynamic memory anyway??:
    Code:
    char fecha1[9];
    char fecha2[9];
    char dummy[9];

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    > i hope u can help me out, im programming on turbo c++ 3 on windows xp
    This mix of the very old and very new cannot be good in the long term

    Perhaps something more with the times - at least something which is ANSI-C
    http://www.thefreecountry.com/developercity/index.html

    In addition to what Monster said

    > strncpy(dummy,fecha1,4);
    > ano1=atoi(dummy);
    strncpy doesn't add a \0 to end the string - so atoi could be in for a long run through lots of memory you don't own

    strncpy(dummy,fecha1,4);
    dummy[4] = '\0';
    ano1=atoi(dummy);

  4. #4
    Me want cookie! Monster's Avatar
    Join Date
    Dec 2001
    Posts
    680
    Originally posted by Salem
    strncpy doesn't add a \0 to end the string - so atoi could be in for a long run through lots of memory you don't own
    Small correction: the strncpy function doesn't add a \0 to the end if the size argument (3rd argument) is less than or equal to the length of the source buffer.

    But Salem it right, in your case it doesn't add a null character so you have to add it yourself.

    And something else:
    Code:
    strncpy(dummy,fecha1,4); 
    ano1=atoi(dummy); 
    strncpy(dummy,fecha1,6); 
    dum=atoi(dummy); 
    mes1=dum-(ano1*100); 
    strncpy(dummy,fecha1,8); 
    dum=atoi(dummy); 
    dia1=dum-((ano1*10000)+(mes1*100));
    You can change this by:
    Code:
    if(strlen(dummy) == 8) /* or >= 8 */
    {
      strncpy(dummy,fecha1,4);
      dummy[4] = '\0';
      ano1=atoi(dummy); 
      strncpy(dummy+4,fecha1,2); 
      dummy[2] = '\0';
      mes1=atoi(dummy); 
      strncpy(dummy+6,fecha1,2); 
      dummy[2] = '\0';
      dia1=atoi(dummy); 
    }
    B.t.w. what happens if I enter more than 9 characters when I enter the date ???

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    My suggestion would be to modify the strncpy function:

    Code:
    
    char *Strncpy( char *target, char *source, int max)
    {
    char *t; 
    char *s;
    
     for(s = source, t = target; (s != NULL) && (*s != 0) && (m < max - 1);  s++, t++, m++)
     {
       *t = *s;
     } 
    
    *t = 0; 
    
     t = target;
    
     return t;
    }
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Sebastiani, what's the m variable about, you've forgotten to declare it.

    Also, there's a few efficiencies you could make. Here's an alternative version. It doesn't check for source and target being NULL, that's upto the caller. max is the number of characters that will be placed in target (not including the null terminator).

    Code:
    char *Strncpy(char *target, char *source, int max)
    {
    	char	*t = target;
    
    	while (*source && max)
    	{
    		*target = *source;
    		source++; target++; max--;
    	}
    
    	*target = '\0';
    	
    	return(t);
    }
    I haven't read the whole thread in detail, so maybe I'm off base here!
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Not to sound nit-picky, but :

    You attached "t" to "target" but then increment "target". You also try to increment "source". You can't do that. Run the function and see for yourself. The compiler treats the char* parameters as if they were the names of arrays, an the copy will fail.

    When max = 0, the chance to guarantee that null term is lost...so your loop should be
    while(max > 0)

    Finally, your point that it is the callers responsibility to check for NULL I have one argument: if perchance "source" is NOT null termed, then checking for a non-NULL pointer is a last-ditch attempt to end the copy loop, which may otherwise run infinitely...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Small correction: the strncpy function doesn't add a \0 to the end if the size argument (3rd argument) is less than or equal to the length of the source buffer.
    What? Your 'correction' makes no sense. So if argument 3 (the size) is greater than the source buffer, you say it terminates it? Really? Where at? What point does it decide to null terminate it? What's your source of this information?

    Actually I'll correct you both, unless my source is wrong:

    According to this...

    The strncpy() function is similar, except that not more
    than n bytes of src are copied. Thus, if there is no null
    byte among the first n bytes of src, the result wil not be
    null-terminated.

    In the case where the length of src is less than that of
    n, the remainder of dest will be padded with nulls.
    See? It will copy the null. Provided that N is long enough to count it. It is possible that my source is implementation specific.

    Quzah.
    Last edited by quzah; 06-21-2002 at 04:18 PM.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User
    Join Date
    Jun 2002
    Posts
    4

    thanks guys

    thanks all for your input, now is working, i need to work on my logic but i dont hate strings anymore.




    Juan Zamudio

  10. #10
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Originally posted by Sebastiani
    >You attached "t" to "target" but then increment "target".
    Yes, but it doesn't matter which you do. You could just as easily put these the other way round, like you imply. You need to keep a pointer to the original target so you can return it at the end of the function.

    >You also try to increment "source". You can't do that. Run the function and see for yourself. The compiler treats the char* parameters as if they were the names of arrays, an the copy will fail.
    The parameters are treated exactly as defined, pointers to chars. This means pointer arithmatic works fine. Here's an example of strcpy() from K&R2 to prove it.
    Code:
    void strcpy(char *s, char *t)
    {
        while (*s++ = *t++)
            ;
    }
    >When max = 0, the chance to guarantee that null term is lost...so your loop should be
    >while(max > 0)
    max>0 is tested (well, kind of) in my loop. I can't be bothered to research this too far, what I wrote compiled/ran as expected (or so I found).

    >Finally, your point that it is the callers responsibility to check for NULL I have one argument: if perchance "source" is NOT null termed, then checking for a non-NULL pointer is a last-ditch attempt to end the copy loop, which may otherwise run infinitely...
    These are two different things.. am I understanding you here? The pointer being NULL will result in my function crashing. This is why the caller should ensure it's a good pointer. The null term of the string should always be there, else we'll probably go onto memory that's not ours. I think we're saying the same thing

    >Not to sound nit-picky, but...
    Please do, it's better that way
    Last edited by Hammer; 06-22-2002 at 05:52 AM.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  11. #11
    Me want cookie! Monster's Avatar
    Join Date
    Dec 2001
    Posts
    680
    Originally posted by quzah


    What? Your 'correction' makes no sense. So if argument 3 (the size) is greater than the source buffer, you say it terminates it? Really? Where at? What point does it decide to null terminate it? What's your source of this information?
    My correction does make sense. If the size argument is greater than the source buffer, the destination buffer will be padded with null characters (MSDN Library).
    Code:
    int main()
    {
      char dest[10];
      strncpy(dest, "Hello", 6); /* string will be null terminated */
      return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Strings Program
    By limergal in forum C++ Programming
    Replies: 4
    Last Post: 12-02-2006, 03:24 PM
  2. Programming using strings
    By jlu0418 in forum C++ Programming
    Replies: 5
    Last Post: 11-26-2006, 08:07 PM
  3. Problems with strings as key in STL maps
    By all_names_taken in forum C++ Programming
    Replies: 3
    Last Post: 01-17-2006, 11:34 AM
  4. Reading strings input by the user...
    By Cmuppet in forum C Programming
    Replies: 13
    Last Post: 07-21-2004, 06:37 AM
  5. menus and strings
    By garycastillo in forum C Programming
    Replies: 3
    Last Post: 04-29-2002, 11:23 AM