Thread: Help with Strings

  1. #1
    Registered User marcelo.br's Avatar
    Join Date
    Nov 2018
    Posts
    45

    Unhappy Help with Strings

    I made the code below to join a printf string, because I will use this variable later!
    I would like to know if there is a better way to do what I did below!

    Code:
    #include <stdio.h>
    #include <string.h>
    
    void main(){
       int NumLinha = 10, QtdCaracteresLinha = 11;
       char Buffer[] = "Giant Text";
       char StrNumLinha[8], StrQtdCaracteresLinha[8], Juntando[BUFSIZ];
       
       printf("Linha %d (%d) %s\n", NumLinha, QtdCaracteresLinha, Buffer);
       
       sprintf(StrNumLinha, "%d", NumLinha);
       sprintf(StrQtdCaracteresLinha, "%d", QtdCaracteresLinha);
       
       strcpy(Juntando, "Linha ");
       strcat(Juntando, StrNumLinha);
       strcat(Juntando, " (");
       strcat(Juntando, StrQtdCaracteresLinha);
       strcat(Juntando, ") ");
       strcat(Juntando, Buffer);
    
       printf(Juntando);
       printf("\n");
    }

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    Code:
    #include <stdio.h>
     
    int main() {
       int NumLinha = 10, QtdCaracteresLinha = 11;
       char Buffer[] = "Giant Text";
       char Juntando[BUFSIZ];
     
       snprintf(Juntando, sizeof Juntando, "Linha %d (%d) %s\n",
                NumLinha, QtdCaracteresLinha, Buffer);
     
       printf("%s\n", Juntando);
     
       return 0;
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User marcelo.br's Avatar
    Join Date
    Nov 2018
    Posts
    45

    Thumbs up Thanks!

    Quote Originally Posted by john.c View Post
    Code:
    #include <stdio.h>
     
    int main() {
       int NumLinha = 10, QtdCaracteresLinha = 11;
       char Buffer[] = "Giant Text";
       char Juntando[BUFSIZ];
     
       snprintf(Juntando, sizeof Juntando, "Linha %d (%d) %s\n",
                NumLinha, QtdCaracteresLinha, Buffer);
     
       printf("%s\n", Juntando);
     
       return 0;
    }
    Thank you very much! I did not know snprintf.
    With that I learned a little more!

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    It's exactly like sprintf, which you did use but for some reason didn't realize that you could do the whole thing with it.
    I used snprintf just to limit the total output so as to not overflow the string.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    > printf(Juntando);
    Just so you know, you should never do this.
    Uncontrolled format string - Wikipedia
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Better code:

    Code:
    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
    
    #ifdef __WINNT__
    # include <stdarg.h>
      
      // Windows libc don't have asprintf function...
      int asprintf ( char **, char *, ... );
    #endif
    
    int main ( void )
    {
      int NumLinha = 10, QtdCaracteresLinha = 11;
      char Buffer[] = "Giant Text";
      char *juntando;
    
      // I'll assume NumLinha can be 2łą-1 (+2147483647), so 10 chars long (plus '\0');
      if ( asprintf ( &juntando, "Linha %d (%d) %s\n", NumLinha, QtdCaracteresLinha, buffer ) == -1 )
      {
        // Error!
        fputs ( "Error alocating memory!\n", stderr );
        return EXIT_FAILURE;
      }
    
      puts ( juntando );  // shows buffer pointed by 'juntando'...
    
      // Free the buffer.
      free ( juntando );
    }
    
    #ifdef __WINNT__
    int asprintf ( char **buffptr, char *fmt, ... )
    {
      int size;
      char tmp[2];
      va_list argp;
    
      /* Gets the total buffer size... */
      va_start ( argp, fmt );
      size = vsnprintf ( tmp, 1, fmt, argp );
    
      if ( size < 1 )
      {
        *s = NULL;
        return -1;
      }
    
      va_end ( argp );
    
      /* Alocates buffer. */
      if ( ( *s = ( char * ) malloc ( size + 1 ) ) == NULL )
        return -1;
    
      /* Finally, fills the buffer. */
      va_start ( argp, fmt );
      vsnprintf ( *s, size + 1, fmt, argp );
      va_end ( argp );
    
      return size;
    }
    #endif

  7. #7
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Compiler errors that I got from my Windows computer...

    ||=== Build: Debug in AlgorithmTest (compiler: GNU GCC Compiler) ===|
    D:\Programming\AlgorithmTest\main.c||In function 'main':|
    D:\Programming\AlgorithmTest\main.c|19|error: 'buffer' undeclared (first use in this function)|
    D:\Programming\AlgorithmTest\main.c|19|note: each undeclared identifier is reported only once for each function it appears in|
    D:\Programming\AlgorithmTest\main.c|15|warning: unused variable 'Buffer' [-Wunused-variable]|
    D:\Programming\AlgorithmTest\main.c||In function 'asprintf':|
    D:\Programming\AlgorithmTest\main.c|45|error: 's' undeclared (first use in this function)|
    D:\Programming\AlgorithmTest\main.c|33|warning: unused parameter 'buffptr' [-Wunused-parameter]|
    ||=== Build failed: 2 error(s), 2 warning(s) (0 minute(s), 0 second(s)) ===|
    Fact - Beethoven wrote his first symphony in C

  8. #8
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Also,
    Code:
    if ( ( *s = ( char * ) malloc ( size + 1 ) ) == NULL )
    FAQ > Casting malloc - Cprogramming.com
    Fact - Beethoven wrote his first symphony in C

  9. #9
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Ok... There are some errors. Here the correct version:

    Code:
    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
     
    #ifdef __DEFINE_ASPRINTF__
    # include <stdarg.h>
       
      // Windows libc don't have asprintf function...
      int asprintf ( char **, char *, ... );
    #endif
     
    int main ( void )
    {
      int NumLinha = 10, QtdCaracteresLinha = 11;
      char buffer[] = "Giant Text";
      char *juntando;
     
      // I'll assume NumLinha can be 2łą-1 (+2147483647), so 10 chars long (plus '\0');
      if ( asprintf ( &juntando, "Linha %d (%d) %s\n", NumLinha, QtdCaracteresLinha, buffer ) == -1 )
      {
        // Error!
        fputs ( "Error alocating memory!\n", stderr );
        return EXIT_FAILURE;
      }
     
      puts ( juntando );  // shows buffer pointed by 'juntando'...
     
      // Free the buffer.
      free ( juntando );
    }
     
    #ifdef __DEFINE_ASPRINTF__
    int asprintf ( char **buffptr, char *fmt, ... )
    {
      int size;
      char tmp[2];
      va_list argp;
     
      /* Gets the total buffer size... */
      va_start ( argp, fmt );
      size = vsnprintf ( tmp, 1, fmt, argp );
     
      if ( size < 1 )
      {
        *buffptr = NULL;
        return -1;
      }
     
      va_end ( argp );
     
      /* Alocates buffer. */
      if ( ( *buffptr = ( char * ) malloc ( size + 1 ) ) == NULL )
        return -1;
     
      /* Finally, fills the buffer. */
      va_start ( argp, fmt );
      vsnprintf ( *buffptr, size + 1, fmt, argp );
      va_end ( argp );
     
      return size;
    }
    #endif
    Use -D__DEFINE_ASPRINTF__ if your compiler don't implement this function (Visual C++, for instance!).
    Last edited by flp1969; 02-18-2019 at 07:10 PM.

  10. #10
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Yep... malloc returns a void pointer and don't require a casting. But this code is supposed to be "universal" and there are compilers that still defines malloc returning a non void pointer.
    This way it is garanteed we don't get warnings...

    There is no harm casting here...

  11. #11
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    Quote Originally Posted by flp1969 View Post
    there are compilers that still defines malloc returning a non void pointer.
    Name one.
    Quote Originally Posted by flp1969 View Post
    There is no harm casting here...
    You don't know what you're talking about.

    And your code is crap.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Quote Originally Posted by flp1969
    But this code is supposed to be "universal" and there are compilers that still defines malloc returning a non void pointer.
    This way it is garanteed we don't get warnings...
    C89/C90 standardised malloc as returning void*, so you're saying that you find it necessary to cater to unnamed compilers that are three decades old... which might be acceptable if you're really paranoid, except that your code is littered with //-style single line comments, a language feature which was not standardised until as recently as 1999 (two decades ago, I know, but your benchmark is four decades, right?). Also, you declared main as returning an int, yet didn't return one (perfectly fine as a special exception for main since C99, but there are compilers that would warn about this, e.g., various versions of gcc with -Wall and -ansi).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    Your initial call to vsnprintf needs work as well.
    Code:
    (gdb) 
    20	  if ( asprintf ( &juntando, "" ) == -1 )
    (gdb) 
    23	    fputs ( "Error alocating memory!\n", stderr );
    I couldn't print an empty string.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  14. #14
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    But this code is supposed to be "universal" and there are compilers that still defines malloc returning a non void pointer
    If the compiler doesn't support standard C, it's a good idea not to use it.

    It might also be worth checking to see if you are accidently using a C++ compiler.
    Last edited by Click_here; 02-19-2019 at 02:03 AM.
    Fact - Beethoven wrote his first symphony in C

  15. #15
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by Click_here View Post
    If the compiler doesn't support standard C, it's a good idea not to use it.

    It might also be worth checking to see if you are accidently using a C++ compiler.
    There are many C "standards": K&R, ANSI, C89, C99, C11 and the new C17. And, sometimes you don't have a choice.

    The code I presented before is clearly C99+ code and I could avoid casting the returning pointer of malloc (because it returns a void ptr), but since I started using C (30 years ago) this casting was traditional (old habbits die hard)...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 04-13-2017, 01:29 AM
  2. Replies: 2
    Last Post: 05-16-2012, 06:08 AM
  3. Swapping strings in an array of strings
    By dannyzimbabwe in forum C Programming
    Replies: 3
    Last Post: 03-03-2009, 12:28 PM

Tags for this Thread