KimchiKimperson
KimchiKimperson

Reputation: 11

Chars being cut out of "custom" toupper statement in C

This is my first time writing in C and I have to write a code that does to upper on a string without actually using to upper.
I have done this however it only works up to 8 characters for some reason....
-----
Here is the input:
hello hello hello hello
-----
Here is the output:
Copy: hello hello hello hello
;▒
The capitalized string is HELLO HEp▒▒▒
The original string is hello hello hello hello

#include <stdio.h>

int strLength(char* str){
     int count;
     for(count=0;str[count] != '\n';count++){}
     return count;
}

char* copyStr(char* str,char* str2){
     for(int i=0;str[i] != '\n';i++){
          char n = str[i];
          str2[i] = n;
     }
     str2[strLength(str)] = '\n';
     return str2;
}

char* upper(char* str){
     char str2[100];
     for(int i=0;str[i] != '\n';i++){
         int current = str[i];
         if((current >= 97) && (current <= 122)){
              char new = str[i];
              str2[i] = new-32;
          }
          else{
               str2[i] = current;
          }
    }
    char* str3 = str2;
    return str3;
}

int main(int argc, char **argv){
     char input[100];
     char inputcopy[100];

     //get the input string
     printf("Enter string: ");
     fgets(input, 100, stdin);

     copyStr(input,inputcopy);
     printf("Copy: %s\n", inputcopy);
     printf("The capitalized string is %s\n",upper(inputcopy));
     printf("The original string is %s",input);
}

Upvotes: 1

Views: 56

Answers (1)

Chris Dodd
Chris Dodd

Reputation: 126408

Obvious problems:

  • not NUL terminating the copy in copyStr
  • returning a pointer to a local variable in upper

In C, you can't pass (as arguments) or return (as a return value) strings "directly" as they are not value types -- instead you must pass or return a pointer. Whenever you deal with pointers, you need to worry about the lifetime of the things pointed at, as if you use the pointer after the lifetime of the pointee has ended, you get undefined behavior.

So in order to "return" a string from a function, you must actually return a pointer to something that has a lifetime that extends after the function has returned (which means it can't be a pointer to a local var of the function). There are generally three way to arrange for that to happen:

  1. pass a pointer to where to put the resulting string as an additional argument (this is what you do with your copyStr function)
  2. use malloc to allocate dynamic space for the string and return a pointer to that.
  3. return a pointer to a static (global) string.

Each of these has its own drawbacks:

  1. the caller has to know how big a string is going to be returned (to create the object that it passes the pointer of) before it even makes the call. Often this is impossible or requires allocating a "worst case" large string or has the danger of overrunning the buffer (causing UB). At the least you often need a second additional argument to specify the size of the buffer.
  2. The caller needs to "take charge" of the returned memory and ensure that it gets freed properly. This becomes part of the implicit contract between caller and callee but is frequently not documented, so is a common source of memory leaks
  3. All calls will generally share the same static global, so it's not reentrant or thread-safe.

Upvotes: 2

Related Questions