ECE 209 Strings

Strings vs. Character Arrays

String literal

char  CourseName1[] = "Computer Systems Programming" ;
char  CourseName2[] = {
        'C', 'o', 'm', 'p', 'u', 't', 'e', 'r', ' ',
        'S', 'y', 's', 't', 'e', 'm', 's', ' ',
        'P', 'r', 'o', 'g', 'r', 'a', 'm', 'm', 'i', 'n', 'g', '\0'
      } ;
char  CourseName3[40] = "Computer Systems Programming" ;
char *CourseName4 = "Computer Systems Programming" ;

Initialization of multidimensional arrays

char courseD[2][29] = {
    "ECE209",
    "Computer Systems Programming"
   } ;
char *courseP[2]   = {
    "ECE209",
    "Computer Systems Programming"
   } ;

According to my C compiler (32-bit Intel), sizeof courseD is 58 and sizeof courseP is 8. However, courseP really requires another 36 (7+29) bytes of memory where the actual strings are stored. There probably is another 58 bytes of storage set aside for the "original" copy of courseD.

Standard library functions

I/O functions

String input functions

scanf Reads strings with %s. Skips beginning whitespace and stops at whitespace. Can avoid buffer overflow with width specifier, e.g., %10s.
gets Reads standard input up to next newline. Discards newline character. Does not provide a way to avoid buffer overflow. Should not be used.
fgets Reads file input up to next newline. Does not discard newline character. Avoids buffer overflow by limiting number of read characters.

String input functions

scanf Reads strings with %s. Skips beginning whitespace and stops at whitespace. Can avoid buffer overflow with width specifier, e.g., %10s.
gets Reads standard input up to next newline. Discards newline character. Does not provide a way to avoid buffer overflow. Should not be used.
fgets Read file input up to next newline. Do not discard newline character. Avoids buffer overflow by limiting number of read characters.

String output functions

printf Writes strings with %s. Outputs size can be limited with width specifier, e.g., %10s.
puts Writes string to standard output. Appends newline at end of string. Does not provide a way to limit output size.
fputs Writes string to file output. Do not append a newline character. Does not provide a way to limit output size.

Conversion functions

atof Converts a string into a double. Fails gracelessly.
atoi Converts a string into an int. Fails gracelessly.
strtol Converts a string into a long int. Harder to use than atol, but much safer. Allows the use of bases other than 10.
strtod Converts a string into a double. Harder to use than atof, but much safer.
sscanf A scanf from a string, not a file.
sprintf A printf to a string, not a file.

Strings library

There are lots of functions in this library. Many of these come in strn... variants which limit the number of characters copied or checked.

strlen Counts the number of characters in a string.
strcpy Copies a string.
strcat Concatenates one strings onto the end of another.
strcmp Compares two strings. Returns a negative number, if the first is less than the second; a positive number, if the first is greater than the second; and zero, if the two are equal.
strchr Finds the first occurrence of a character within a string.
strrchr Finds the last (rightmost) occurrence of a character within a string.
strstr Finds the first occurrence of one string within another.

Command line arguments

To read command-line arguments used the non-void prototype.

int main(int argc, char *argv[]) ;

argc is the number of command line arguments and argv[i] is the i'th command line arguments. The name of the program will be argv[0].

Tasks to try

Try writing some of the following tasks.

Printing command line arguments

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

int main(int argc, char* argv[]) {
  int i ;
  for (i=0; i<argc; ++i) {
    printf("  %2d: %s\n", i, argv[i]) ;
  }
    
  return (EXIT_SUCCESS);
}

Useful driver for string transformation

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

#define BSIZE 100

int Transform(const char *, char *) ;

int main(int argc, char* argv[]) {
  char outString[2*BSIZE] ;
  if (argc < 1) {
    return EXIT_FAILURE ;
  }
  if (strlen(argv[1]) > BSIZE) {
    return EXIT_FAILURE ;
  }
  if (!Transform(argv[1], outString)) {
    printf("\"%s\" ==> \"%s\"\n", argv[1], outString) ;
    return EXIT_SUCCESS;
  } else
    return EXIT_FAILURE ;
}

Transform names to "Last, First" display

#include <string.h>

int Transform(const char *inString, char *outString) {
  char *lastNameP ;
  int firstPartSize, nameSize ;
  if ((lastNameP = strrchr(inString, ' ')) == NULL) {
    return 1 ;
  }
  nameSize = strlen(inString) ;
  firstPartSize = lastNameP - inString ;
  strcpy(outString, lastNameP+1) ;
  strcat(outString, ", ") ;
  strncat(outString, inString, firstPartSize) ;
  outString[nameSize+1] = '\0' ;
  return 0 ;
}
#include <string.h>
#include <stdio.h>

int Transform(const char *inString, char *outString) {
  char *lastNameP ;
  if ((lastNameP = strrchr(inString, ' ')) == NULL) {
    return 1 ;
  }
  sprintf(outString, "%s, %.*s", lastNameP+1, lastNameP-inString, inString) ;
  return 0 ;
}

Transform names to login id

#include <string.h>
#include <ctype.h>

int Transform(const char *inString, char *outString) {
  char *lastNameP, *middleNameP, *lastOfOutput ;
  if ((lastNameP = strrchr(inString, ' ')) == NULL) {
    return 1 ;
  }
  strncpy(outString, lastNameP+1, 6) ;
  outString[0] = tolower(outString[0]) ;
  outString[6] = '\0' ;
  lastOfOutput = outString + strlen(outString) ;
  *lastOfOutput++ = tolower(inString[0]) ;
  middleNameP = strchr(inString, ' ') ;
  if (middleNameP != lastNameP) {
    *lastOfOutput++ = tolower(middleNameP[1]) ;
  }
  *lastOfOutput = '\0' ;
  return 0 ;
}

Replace every "2008" with "2010"

#include <string.h>

int Transform(const char *inString, char *outString) {
  char *outP, *matchP ;
  strcpy(outString, inString) ;
  outP = outString ;
  while ((matchP = strstr(outString, "2008")) != NULL) {
    strncpy(matchP, "2010", 4) ;
    outString += 4 ;
  }
  return 0 ;
}