two functions - getting char and work on pointer - c

in C:
Im trying to write 2 functions one is getting from the user a line (string) and sending it to another function that remove (if exist) blank space from start of the string.
I am trying to make the "remove_space" function work on pointer, alter it by making it point to the continue of the string without the space.
for example:
lets say the user type:
" hi123"
and i save this string in some pointer
i want to send this pointer to "remove_space" function and make the pointer point at "hi123" without the spacing starts...
for now.. i have some problems with the pointers from what i see.
this is what I wrote:
void remove_space(char** st1)/**function to remove space**/
{
char* temp_st = strtok(st1, " ");
strcpy(st1, temp_st);
}
void read_comp(void)
{
printf("read_comp FUNCTION\n");
char* st1; /**read the rest of the input**/
fgets(st1,30,stdin);
remove_space(st1);
printf("%s\n",st1);
}

You haven't allocate memory to store a string in st1.
char st1[30];
Also, you don't need a char** here.
void remove_space(char *st1)
{
char *temp_st = strtok(st1, " ");
strcpy(st1, temp_st);
}

Related

Array of strings reading its input from file.txt C programming

I am having a problem and cant tell what is it.
struct arrayDB {
char *user[MAX_SIZE];
char *pass[MAX_SIZE];
char db[10][2];
};
void readFile(char fileName[100])
{
char* word ;
char line[90];
FILE *passFile;
int rowC=0;
int chk=0;
passFile=fopen(fileName,"rt");
while(fgets(line,90,passFile)!=NULL)
{
word=strtok(line," ");
rowC=rowC+1;
while(word!=NULL)
{
printf("Count=%i \n",rowC);
if(chk==0)
{
printf("word:%s\n",word);
DB.user[rowC]=word;
chk=1;
}
else
{
printf("word:%s\n",word);
DB.pass[rowC]=word;
}
printf("r=%s , c=%s\n",DB.user[rowC],DB.pass[rowC]);
word=strtok(NULL," ");
}
chk=0;
}
int i;
for(i=1; i<6;i++)
{
printf("- %s , %s \n",DB.user[i],DB.pass[i]);
}
}
but the output I am getting that all the array elements is the same value which is the last word in the file
as you can see in the pic
thanks
You're reading every line into the same string line. Then when you use strtok(), it's returning pointers into this string, and you're storing these pointers into DB. So all the records in DB are pointing to locations in line, which gets overwritten each time you read another line from the file. When everything is done, line contains the contents of the last line of the file, and all the DB entries point to that.
Another problem is that line is a local variable, and pointers to it become invalid when the function returns.
To solve both problems, you need to make copies of the string and store these in DB. For example:
DB.user[rowC]= strdup(word);
This also means that when you're done with a DB record, you need to call free(DB.user[i])
Some suggestions:
First, learn to use a debugger. There are free ones, get one and turn it on to find all of these errors (that is what I did here)
Next, for the code example you show to compile, the struct definition needs to support your code (currently, DB is not defined)
typedef struct
{
char *user[MAX_SIZE];
char *pass[MAX_SIZE];
char db[10][2];
}arrayDB;
arrayDB DB;//define DB
Next,
you need to allocate space for your string arrays:
something like:
for(i=0;i<MAX_SIZE;i++ )
{
DB.user[i] = malloc(100);
DB.pass[i] = malloc(100);
}
Next, don't forget to free them when done using them.
for(i=0;i<MAX_SIZE;i++ )
{
free(DB.user[i]);
free(DB.pass[i]);
}
Next, you cannot assign a string using an equal operator:
DB.pass[rowC]=word;
use strcpy (or some other string function) instead:
strcpy(DB.pass[rowC],word);
Next, this line:
printf("r=%s , c=%s\n",DB.user[rowC],DB.pass[rowC]);
Is called after a conditional statement where either DB.user[rowC] or DB.pass[rowC] will be written to, never both. Suggest splitting this printf statement to print one or the other, and place it into the appropriate conditional branch.

How to assign a char* to an array of char* with unique entries?

Okay so that wasn't very clear. What I am trying to do is this:
while (//something) {
char * tempuser;
char * users[100];
tempuser = "bobsmith" //I'm not actually doing this. But using a method that does the same thing
users[i] = tempuser;
}
Where "bobsmith" is is different everytime through the loop. If I run this, as is, 5 times and the last entry is "janetsmith" all 5 places in the array before that, regardless of being different when assigned, all end up as "janetsmith". How should I assign users[i] so that it has a different value in all indexes?
Do not create the array users in loop body, and use strdup to create new string with the same content inside the array. Remember that You are using pointers not some kind of string objects. Each entry in array holds the address of the text inside memory.
char *users[100]={0}; //one hundred pointers that are null so You don't use a wild one.
int i=0;
while(/*whatever*/) {
char *tmp=getsometext(); //returns char pointer
users[i++]=strdup(tmp); //copies contents pointed by tmp into new memory location and returns its address
}
//don't forget to free every pointer when You are done.
It is because you are assigning address of the variable tempuser. By the end of it all, it will always hold the address of "janetsmith". Try creating the variable dynamically using malloc() function.
char * users[100]; //with this you can use it outside while
while (//something) {
static unsigned int i = 0;
//char * tempuser;
//tempuser = "bobsmith" //I'm not actually doing this. But using a method that does the same thing
users[i] = method_which_return_char_pointer();
i++;
if( 100 <= i)
i=0;
}
this what from your brief Question explanation .

Assign a string created in a function to a typedef structure array created in main

Alright. So I have this program in C where I take a string with arguments and values (Such as: "GO 45 STOP 15"). The goal is to parse the string and place the argument with its corresponding value into a typedef structure to work with later on.
This is what my structure looks like:
typedef struct {
char* keyword;
double value;
} parameter;
Here are some copies of my code that I am having issues with.
Both main() and initParams() are in the same file and therefore both have access to the same #defines...
main():
#include <stdio.h>
#include <stdlib.h>
#include "findArgs.h"
#define STR0_SIZE 80
#define LIST_SIZE 4
#define MAX_PARAMS 15
void main(){
int i;
char str0[STR0_SIZE] = "LEFT 45 GO 686 GO 34.3 STOP 56 RIGHT 26"; //Input String
char* wordList[LIST_SIZE]={"GO", "STOP", "LEFT", "RIGHT"};
int num_arg = 0; //Number of arguements in str0 (each space denotes the end of an arg)
parameter* param;
initParams(param);
replaceSpaces(str0, &num_arg);
findWords(param, str0, num_arg);
}
initParams:
void initParams(parameter* param){
int ctr0, ctr1;
param = (parameter*) malloc(MAX_PARAMS * sizeof(parameter));
printf("\n%i\n", sizeof(parameter));
for(ctr0=0;ctr0<MAX_PARAMS;ctr0++){
param[ctr0].keyword = "";
param[ctr0].value = 0;
}
}
ok some quick explainations. initParams is for allocating the memory for each of my parameters. I am assuming that I will not have any idea how many parameters will be included in the string and plan on determining the number in the string later in the program. I do know that I will not accept more than parameters in the string.
After allocating the memory, I loop through each one and initialize each value to either an empty string or 0. (I do realize this is probably unnecessary, however I have done this as part of my code troubleshooting.
Continuing on, replaceSpaces() simply loops through the string and replaces each occurrence of ' ' with a '\0'. It also counts the number of arguements present in the string so that I know how many new strings I have just created by adding null terminators.
Now the tricky part in which I am having difficulty.
#define MAX_ARG_LENGTH 20
void findWords(parameter* param, char* str0, int num_arg){
parameter temp[countWords(str0, num_arg)];
int i;
int ctr0,ctr1, ctr2=0;
int word=0; //flag
char tempStr[MAX_ARG_LENGTH]="";
char* c0 = str0;
for(ctr0=0; ctr0<num_arg; ctr0++){
word=0;
ctr1=0;
if(((*c0 > 'a') && (*c0 <'z')) || ((*c0 > 'A') && (*c0 <'Z'))){
word=1;
tempStr[ctr1]=*c0;
ctr1++;
}
while(*c0 != '\0'){
c0++;
if(word)
tempStr[ctr1++] = *c0;
printf("\ntempStr: '%s'\n", tempStr);
}
if(word){
param[ctr2].keyword = tempStr;
printf("%s\n", param[ctr2].keyword);
ctr2++;
}
c0++;
}
for(i=0; i<num_arg/2;i++){
printf("'%s'\n", param[i].keyword);
printf("'%g'\n", param[i].value);
}
}
This function works properly at finding each word in the string and storing it in tempStr. My issue is with assigning it to my parameter array back in my main(). I have tried assigning them to a temp array of parameters and then setting "param" equal to the temp array. However due to the fact that param is a pointer, when I assign it a local location, after the function is finished, the memory is freed and lost. Enter my idea to use malloc to predefine memory for them and assign it after.
This is my current output when I compile and run the code. I added comments to clarify
16 //sizeof(parameter)
5 //Number of words in str0
LEFT
GO
GO
STOP
RIGHT
'RIGHT' //Things in single quotes are prints from the array of parameters
'8.05316e-315'
'RIGHT'
'0'
'RIGHT'
'8.04051e-315'
'RIGHT'
'0'
'RIGHT'
'0'
MAIN: //I printed these in main using the same for loop seen in findWord()
'▒▒'
'8.05316e-315'
'▒▒'
'0'
'▒▒'
'8.04051e-315'
'▒▒'
'0'
'▒▒'
'0'
If anyone can help me properly assign the contents of tempStr to a parameter in my array declared in main I would be greatly appreciative. Please Let me know if you need any more information.
THANK YOU ALL!! I GOT IT!!!
Rather than make "tempStr" I just assgned the characters directly to the param[index].keyword. It worked like a charm
Thank you guys very much! I had read many different Qs and As here before but this was my first time posting. I am very excited with how quickly you guys were able to reply.
Thanks again!
~Nick
I think you are misunderstanding what param[ctr2].keyword = tempStr; does It does not copy the string in tempstr to keyword it just makes keyword point to tempstr, which means all the keywords will point to the tempStr variable and will be invalid if you access it outside this function.
What you want to do is to make
char* keyword;
into
char keyword[MAX_ARG_LENGTH];
And use something like strcpy or strncpy to do the copying.
You also do not appear to be setting value anywhere

Returning populated string array from function C

It's the first time posting so I apologise for any confusion:
I am writing a function like this:
int myFunc(char* inputStr, int *argCTemp, char** argVTemp[]);
The purpose of my function is to take a copy of the input string (basically any user input) and then use strtok to convert it to tokens and populate an array via an array pointer (argV). When myFunc is finished, hopefully I have the argument count and array of strings from my inputStr string.
Here is an example of how I call it:
int main(int argc, char** argv[])
{
int argCTemp = -1;
char** argVTemp;
// 1 Do Stuff
// 2 Get input string from user
// 3 then call myfunc like this:
myFunc(inputStr, &argCTemp, &argVTemp);
// 4: I get garbage whenever I try to use "argVTemp[i]"
}
My Questions: How should I best do this in a safe and consistent way. How do the pro's do this?
I don't use malloc because:
I don't know the number of arguments or the length of each for my input (to dynamically allocate the space). I figured that's why I use pointers
since I declare it in the main function, I thought the pointers to/memory used by argCTemp and argVTemp would be fine/remain in scope even if they are on the stack.
I know when myFunc exits it invalidates any stack references it created, so that's why I sent it pointers from a calling function. Should I be using pointers and malloc and such or what?
Last thing: before myfunc exits, I check to see the values of argCTemp and argVTemp and they have valid content. I am setting argCtemp and argVtemp like this:
(*argCTemp) = argCount;
(*argVTemp)[0] = "foo";
and it seems to be working just fine BEFORE the function exits. Since I'm setting pointers somewhere else in memory, I'm confused why the reference is failing. I tried using malloc INSIDE myFunc when setting the pointers and it is still becoming garbage when myFunc ends and is read by the calling function.
I'm sorry if any of this is confusing and thank you in advance for any help.
Since "don't know the number of arguments or the length of each for my input ", you can use malloc also. When your buffer abouting full, you should realloc your buffer.
The better way: You needn't store whole input. A line, a token or a block is better. Just set a static array to store them. and maybe hash is better if your input more than 100 mb.
I'm sorry for my poor English.
You send an uninitialized pointer (you call is isn't correct as well, you don't need the & ) to the function, this pointer points to some random place and that is why you get garbage, you can also get segmentation fault.
You can do one of the two.
Per allocate a large enough array which can be static for example
static char * arr[MAX SIZE] and send it (char **)&arr in the function call, or run twice and use malloc.
You should also pass the max size, or use constant and make sure you don't pass it.
Lets say you the number of tokens in int n then
char * arr[] = malloc(sizeof(int *)*n);
this will create array of pointers, now you pass it to your populate function by calling
it with (char **)&arr, and use it like you did in your code
for example (*argVTemp)[0] = ;.
(when the array is not needed any more don't forget to free it by caliing free(arr))
Generally speaking, since you don't know how many tokens will be in the result you'll need to allocate the array dynamically using malloc(), realloc() and/or some equivalent. Alternatively you can have the caller pass in array along with the array's size and return an error indication if the array isn't large enough (I do this for simple command parsers on embedded systems where dynamic allocation isn't appropriate).
Here's an example that allocates the returned array in small increments:
static
char** myFunc_realloc( char** arr, size_t* elements)
{
enum {
allocation_chunk = 16
};
*elements += allocation_chunk;
char** tmp = (char**) realloc( arr, (*elements) * sizeof(char*));
if (!tmp) {
abort(); // or whatever error handling
}
return tmp;
}
void myFunc_free( char** argv)
{
free(argv);
}
int myFunc(char* inputStr, int *argCTemp, char** argVTemp[])
{
size_t argv_elements = 0;
size_t argv_used = 0;
char** argv_arr = NULL;
char* token = strtok( inputStr, " ");
while (token) {
if ((argv_used+1) >= argv_elements) {
// we need to realloc - the +1 is because we want an extra
// element for the NULL sentinel
argv_arr = myFunc_realloc( argv_arr, &argv_elements);
}
argv_arr[argv_used] = token;
++argv_used;
token = strtok( NULL, " ");
}
if ((argv_used+1) >= argv_elements) {
argv_arr = myFunc_realloc( argv_arr, &argv_elements);
}
argv_arr[argv_used] = NULL;
*argCTemp = argv_used;
*argVTemp = argv_arr;
return argv_used;
}
Some notes:
if an allocation fails, the program is terminated. You may need different error handling.
the passed in input string is 'corrupted'. This might not be an appropriate interface for your function (in general, I'd prefer that a function like this not destroy the input data).
the user of the function should call myFunc_free() to deallocate the returned array. Currently this is a simple wrapper for free(), but this gives you flexibility to do more sophisticated things (like allocating memory for the tokens so you don't have to destroy the input string).

How do I return an array of strings from a recursive function?

How do I return an array of strings from a recursive function?
For example::
char ** jumble( char *jumbStr)//reccurring function
{
char *finalJumble[100];
...code goes here...call jumble again..code goes here
return finalJumble;
}
Thanks in advance.
In C, you cannot return a string from a function. You can only return a pointer to a string. Therefore, you have to pass the string you want returned as a parameter to the function (DO NOT use global variables, or function local static variables) as follows:
char *func(char *string, size_t stringSize) {
/* Fill the string as wanted */
return string;
}
If you want to return an array of strings, this is even more complex, above all if the size of the array varies. The best IMHO could be to return all the strings in the same string, concatenating the strings in the string buffer, and an empty string as marker for the last string.
char *string = "foo\0bar\0foobar\0";
Your current implementation is not correct as it returns a pointer to variables that are defined in the local function scope.
(If you really do C++, then return an std::vector<std::string>.)
Your implementation is not correct since you are passing a pointer to a local variable that will go out of scope rather quickly and then you are left with a null pointer and eventually a crash.
If you still want to continue this approach, then pass by reference (&) an array of characters to that function and stop recursing once you have reached the desired end point. Once you are finished, you should have the 'jumbled' characters you need.
You don't :-)
Seriously, your code will create a copy of the finalJumble array on every iteration and you don't want that I believe. And as noted elsewhere finalJumble will go out of scope ... it will sometimes work but other times that memory will be reclaimed and the application will crash.
So you'd generate the jumble array outside the jumble method:
void jumble_client( char *jumbStr)
char *finalJumble[100];
jumble(finalJuble, jumbStr);
... use finalJumble ...
}
void jumble( char **jumble, char *jumbStr)
{
...code goes here...call jumble again..code goes here
}
And of course you'd use the stl datatypes instead of char arrays and you might want to examine whether it might be sensible to write a jumble class that has the finalJumble data as a member. But all that is a little further down the road. Nevertheless once you got the original problem solved try to find out how to do that to learn more.
I would pass a vector of strings as a parameter, by reference. You can always use the return value for error checking.
typedef std::vector<std::string> TJumbleVector;
int jumble(char* jumbStr, TJumbleVector& finalJumble) //recurring function
{
int err = 0; // error checking
...code goes here...call jumble again..code goes here
// finalJumble.push_back(aGivenString);
return err;
}
If you want to do it in C, you can keep track of the number of strings, do a malloc at the last recursive call, and fill the array after each recursive call. You should keep in mind that the caller should free the allocated memory. Another option is that the caller does a first call to see how much space he needs for the array, then does the malloc, and the call to jumble:
char** jumble(char* jumbStr)
{
return recursiveJumble(jumbStr, 0);
}
char** recursiveJumble(char* jumbStr, unsigned int numberOfElements)
{
char** ret = NULL;
if (/*baseCase*/)
{
ret = (char**) malloc(numberOfElements * sizeof(char*));
}
else
{
ret = jumble(/*restOfJumbStr*/, numberOfElements+1);
ret[numberOfElements] = /*aGivenString*/;
}
return ret;
}

Resources