• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 851
  • Last Modified:

Passing and Retrieving variables to and from functions?

I have been going through an exercise of passing, and trying to receive back, variables into different situations and have hit some snags.  Doing so with integers is fairly strait forward and I have no issues with that.  My issue is wen working with strings.

char *
char
const char
etc..

Here is a simple example of what I am talking about:
____________________________________________________________________
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int power (int base, int exp);
const char reverse (char *num);
char commify (char *string);

int main (int argc, char *argv[]) {
   if (argc <= 1) {
      perror("Missing Required Argument!");
      exit(1);
   }

   printf("Value of %d raised to %d is %u\n", atoi(argv[1]), atoi(argv[2]), power((int)atoi(argv[1]), (int)atoi(argv[2])));
   return 0;
}

int power (int base, int exp) {
   int i;
   unsigned int answer = 1;
   for (i=1; i<=exp; i++)
      answer *= base;

   answer = commify((char *)answer);
   return answer;
}

char commify (char *string) {
   int i = 0; char c;
   char *rev; char *rtn;

   if ((rev = malloc(strlen(string)+1)) == NULL) {
      perror("Memory allocation error for rev");
      exit(1);
   }

   if ((rtn = malloc(strlen(string)+1)) == NULL) {
      perror("Memory allocation error for rtn");
      exit(1);
   }

   strcpy(rev, reverse(string));
   while ((c = gets(rev)) != EOF) {
      if (++i <= 3) {
         strcat(rtn, c);
      } else {
         i = 0;
         strcat(rtn, c);
         strcat(rtn, ',');
      }
   }

   return rtn;
}

const char reverse(char *num) {
   char c; int j;
   int i = 1;
   char *string[100];
   char *rev;

   if ((rev = malloc(strlen(string)+1)) == NULL) {
      perror("Memory allocation error for rev");
      exit(1);
   }

   while((c = gets(num)) != EOF) {
      string[i] = c;
      i++;
   }

   for (j=i; j!=0; j--) {
      strcat(rev, string[j]);
   }

   return (const char *)rev;
}
_____________________________________________________________

This is a program that will take in two command line arguments and raise one to the power of the other and return the results.  I had this working properly with just main() and power() using ints, but then I decided to try and add commas where they are suppose to be for readability.  This is where the commify() and reverse() functions came in and where I am having issues.

The logic of the reverse or the commify may not work properly yet but I am not interested in that.  I mainly want to know how I can pass the strings into these functions and return the values back.  The code is pretty "all-over-the-place" because I have been trying numerous method and keep getting different errors.  Like the malloc()'s are there because I was getting an error about casting an integer into a pointer of different size.

Here are the current compiler erros I receive as of now.

_____________________________________________________________
exp.c: In function âcommifyâ:
exp.c:43: warning: passing argument 2 of âstrcpyâ makes pointer from integer without a cast
exp.c:44: warning: assignment makes integer from pointer without a cast
exp.c:46: warning: passing argument 2 of âstrcatâ makes pointer from integer without a cast
exp.c:49: warning: passing argument 2 of âstrcatâ makes pointer from integer without a cast
exp.c:50: warning: passing argument 2 of âstrcatâ makes pointer from integer without a cast
exp.c:54: warning: return makes integer from pointer without a cast
exp.c: In function âreverseâ:
exp.c:63: warning: passing argument 1 of âstrlenâ from incompatible pointer type
exp.c:68: warning: assignment makes integer from pointer without a cast
exp.c:69: warning: assignment makes pointer from integer without a cast
exp.c:77: warning: return makes integer from pointer without a cast
/tmp/cc2GoDNA.o(.text+0x214): In function `commify':
exp.c: warning: the `gets' function is dangerous and should not be used.
_____________________________________________________________

It also complains about me using gets(), probably because of the unsafe nature of it but I could not find any other function that will read from a string and not stdin or a file handle.  Any help is appreciated.
0
ZiaTioN
Asked:
ZiaTioN
  • 5
  • 4
  • 2
2 Solutions
 
ozoCommented:
gets(string) reads from stdin into the string and returns a pointer to the string or NULL
it looks like you are trying to use it to read a character from string
This compiles and runs, but still may not be doing what you intended

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

char *power (int base, int exp);
const char *reverse (char *num);
char *commify (char *string);

int main (int argc, char *argv[]) {
   if (argc <= 1) {
      perror("Missing Required Argument!");
      exit(1);
   }

   printf("Value of %d raised to %d is %s\n", atoi(argv[1]), atoi(argv[2]), power((int)atoi(argv[1]), (int)atoi(argv[2])));
   return 0;
}

char * power (int base, int exp) {
   int i;
   unsigned int answer = 1;
   char string[100];
   for (i=1; i<=exp; i++)
      answer *= base;
   sprintf(string,"%d",answer);
   return commify((char *)string);
}

char *commify (char *string) {
   int i = 0; char c[2];
   char *rev; char *rtn;

   if ((rev = malloc(strlen(string)+1)) == NULL) {
      perror("Memory allocation error for rev");
      exit(1);
   }

   if ((rtn = malloc(strlen(string)+1)) == NULL) {
      perror("Memory allocation error for rtn");
      exit(1);
   }

   strcpy(rev, reverse(string));
   while ((c[0] = *rev++) != '\0') {
      c[1]='\0';
      if (++i <= 3) {
         strcat(rtn, c);
      } else {
         i = 0;
         strcat(rtn, c);
         strcat(rtn, ",");
      }
   }

   return rtn;
}

const char *reverse(char *num) {
   char c; int j;
   int i = 1;
   char string[100];
   char *rev;

   if ((rev = malloc(strlen(num)+1)) == NULL) {
      perror("Memory allocation error for rev");
      exit(1);
   }

   while((c = *num++) != '\0') {
      string[i] = c;
      i++;
   }

   for (j=0; i--!=0; j++) {
      rev[j] =  string[i];
   }
   rev[j]='\0';
   return (const char *)rev;
}
0
 
PaulCaswellCommented:
Hi ZiaTioN,

Your primary mistake is here:

const char reverse (char *num);
char commify (char *string);

I expect you dont want these functions to return on character, you want them to return strings:

const char * reverse (char *num);
char * commify (char *string);


Paul
0
 
ZiaTioNAuthor Commented:
ozo,

Glad to get your assistance instead of trying to beat you to the new questions in the perl section.  I saw you changed some of the code in the reverse() and commify() functions in the for and while loops which I understood but it was the changes to the prototypes I did not understand.

Paul,

Thank you for explaining the prototype changes before I could ask about them. lol...
Why does that change allow a string to be returned instead of just a character?
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
ZiaTioNAuthor Commented:
Also I had one last question (besides the prototype question).  The application works now but when I raise 10 to anything larger than 9 (creating more than 10 digits) I get some random number returned.  I was sure this was because of the limits of int so I have tried unsigned to give it more of a positive range and also long int but the same thing happens.
0
 
ZiaTioNAuthor Commented:
Ok it looks like the limits of int on my system is 2147483647 which is 4294967295 (2^32) divided by 2 and subtracted by 1 (to account for 0 as a positive number).  This limit is the same on my system as long in which is why there was no difference (modern linux system not hampered by the old 2^16 int limit).  When I use unsigned long it I basically gets rid of the negative split so the limit is 4294967295.  All of these values are maxed at 10 digits so this would explain why anything larger than 10 digits gets hosed.

Is there anything that can be used to represent a value larger than 10 digits?
0
 
ozoCommented:
limits.h should list the limits on your system
ULONG_MAX must be at least 4294967295 but some implementations provide more
0
 
ozoCommented:
a common extension provided non portably by some implementatsion is to have other arithmetic types such as long long int
0
 
ZiaTioNAuthor Commented:
Yeah I used limits.h to find the limits I had posted.  I will have to try the long long int option.

So what is the deal with adding the * to the function prototypes and declerations?  I was under the impression that the * denoted a pointer.  How does this allow it to return a string over a character?

Sorry, I am just trying to get a grasp on this for future reference...
0
 
PaulCaswellCommented:
Hi ZiaTioN,

A char * is not necessarily a string, its just a pointer. It may even point to nothing at all, random data etc. Using 'malloc' as you do, allows you to 'create' a string inside a function and instead of returning the whole string back as a result, you just need to return a pointer to it.

Paul
0
 
ozoCommented:
char commify (char *string);
returns a char
char *commify (char *string);
returns a pointer to char
a string is represented by a pointer to the first char of the string
you declared the char *string argument this way
string[0] is the first char of string
string[1] is the next char of string, etc.
standard string funnctions expect strings to be terminated by a null char
0
 
ZiaTioNAuthor Commented:
Ahh so a char * in a function is still a pointer.  I have never seen it used in this way before.

Thank you both!

Split 300 to ozo and 200 to Paul.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 5
  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now