I want to write a function that adds an Entry to the first free slot of an array list (if there is a slot free) and a function that merges all those entries to one "String" (I know there are no strings) separated by ', '.
Example list contains: "Anna", "Alex", "Anton" in this order
Output:"Anna,Alex,Anton".
This is the .c file (only the toDo's should be done)
/** The function adds an entry name to the array list at the
* first free position, if such a position exists.
* If there is no free space, ie no NULL entry,
* the array remains unchanged. When inserting a name,
* First, the same amount of memory is allocated on the heap using malloc
* (note space for a final \ 0). After that
* we use strncpy to convert the string name into the allocated
* Memory area copied.
* #param list: Array of \0 terminated strings
* #param listsize: size of array
* #param name: \0 terminated string that should be copied into the array
*/
void addNameToList(char **list, size_t listsize, char *name) {
//toDo
}
/** The function adds all entries in the list array to one separated by ','
* zero-terminated string that is stored in destbuffer.
* Entries with the value NULL are not added.
* So that chained calls are possible, the function returns the
* Pointer destbuffer as return value.
* Example: The list contains the names "Anna", "Alex", "Anton" in this
* Sequence. The function returns "Anna, Alex, Anton".
* #param list: array of \0 terminated strings
* #param listsize: size of array
* #param destbuffer: destinationbuffer
* #param buffersize: size of destbuffer
* #return destbuffer
*/
char *printListToString(char **list, size_t listsize, char *destbuffer, size_t buffersize) {
//toDo
return destbuffer;
}
void freeList(char **list, size_t listsize) {
size_t index = 0;
for (index = 0; index < listsize; index++)
if (list[index] != NULL)
free(list[index]);
free(list);
}
char **initList(size_t size) {
return calloc(size, sizeof(char *));
}
This is the given Main (not to change):
int main(void) {
char **names;
char outputbuffer[100];
names = initList(LIST_SIZE);
addNameToList(names, LIST_SIZE, "Alice");
addNameToList(names, LIST_SIZE, "Bob");
addNameToList(names, LIST_SIZE, "Carla");
addNameToList(names, LIST_SIZE, "Dana");
addNameToList(names, LIST_SIZE, "Eve");
printListToString(names, LIST_SIZE, outputbuffer, 100);
printf("%s\n", outputbuffer); //Output: Alice,Bob,Carla,Dana,Eve
freeList(names,LIST_SIZE);
}
What I have tried so far (not working):
char *printListToString(char **list, size_t listsize, char *destbuffer, size_t buffersize) {
int k = 1;
for(int i = 0; i < listsize; i++) {
if(list != NULL) {
strcpy_s(destbuffer, sizeof list, list);
}
if(list == '\0') {
destbuffer[i] =',';
destbuffer[k] = ' ';
}
k++;
}
return destbuffer;
}
The code above:
k is always one step ahead of i, so it can add a space right after the ',' (which is added at i)
I iterate thru the list and check whether an entry is NULL or not if its not NULL it should copy the name from the list into the destbuffer
Since the names end with \0 I thought I can just add , and a space right after I copied the name
void addNameToList(char **list, size_t listsize, char *name) {
malloc(sizeof name);
if(sizeof list != listsize) {
for(int i = 0; i < listsize; i++) {
if(list[i] == NULL) {
list[i] = name;
}
}
}
}
the code above:
saving memory for the name
check if list is full
if not I add the name at the first place thats null
(Note that I dont have any experience in C, only Python and Java. The "code above" section is what the code meant to do, not what its actually doing)
Let's consider the last snippet
void addNameToList(char **list, size_t listsize, char *name) {
// ^^^^^^^^^^
// 'name' is a POINTER. Not an array, nor a C-string (NULL-terminated array
// of char). It may point to the first element of one of those, though.
malloc(sizeof name);
// ^^^^^^^^^^^ This returns the size, in bytes, of a POINTER to char.
// Maybe 8, but surely not the number of characters up to the first '\0'
// from the one pointed by 'name'. To get that, you need
// strlen(name)
// Besides, 'malloc' RETURNS a pointer and you NEED it, because the whole
// point of that function call is to allocate enough memory to store
// your object and you better know WHERE this space is. If only to later
// release that resorce and avoid any leak.
if(sizeof list != listsize) {
// ^^^^^^^^^^^ Again, it's the size of a pointer to a pointer to char...
// Unfortunately, it's also probably different from listsize, so that
// it's harder to catch this error. Also, You don't need this check...
for(int i = 0; i < listsize; i++) {
// ^^^^^^^^^^^^ ... Because there already is this.
if(list[i] == NULL) {
list[i] = name;
// ^ This is a shallow copy, only the value OF the pointer
// (let's say the memory address) is copied, NOT all the elements
// of the string.
// Here is where the memory should be allocated, something like
// size_t size = strlen(name);
// list[i] = malloc(size);
// if ( list[i] == NULL ) {
/* malloc may fail... */
// }
// Then, the array must be copied. Your teacher mentioned
// 'strncpy'.
}
}
}
}
The other function, printListToString is broken too, perhaps even worse than the previous one.
k is always one step ahead of i, so it can add a space right after the ',' (which is added at i)
To do that, i + 1 could be enough, but that's not the point. There should be two different indices, one to itarate over list and one for destbuffer.
I iterate thru the list and check whether an entry is NULL or not if its not NULL it should copy the name from the list into the destbuffer
Unfortunately, in all its occurrences, list is written without an [i], so that no name in the list is actually accessed.
Since the names end with \0 I thought I can just add , and a space right after I copied the name
I'd do something like
char *printListToString( char **list, size_t listsize
, char *destbuffer, size_t buffersize) {
size_t j = 0;
for (size_t i = 0; i < listsize; ++i) {
if ( list[i] != NULL ) {
// Add ", ", but only if it's not the first name.
if ( j != 0 ) {
if ( j + 2 > buffersize )
break;
destbuffer[j++] = ',';
destbuffer[j++] = ' ';
}
// Copy the name. Feel free to use a library function instead.
for ( size_t k = 0; list[i][k] != '\0' && j < buffersize; ++k, ++j ) {
destbuffer[j] = list[i][k];
}
}
}
destbuffer[j] = '\0';
return destbuffer;
}
Related
I'm trying to get to read string input from user and store it in two dim array using pointers.
I'm getting Access violation reading location exception when trying to use those strings.
first I declared char*** that will store pointers for two dim array , then I use for loop to initial two dim array for each cell.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORDLEN 80
#define DEFLEN 200
#define KEYVALUE 2
char*** MallocDic(int dictionarySize);
char** MallocDicElement(char* word, char* definition);
void PrintDictionary(char*** dictionary, int dictionarySize);
int main()
{
int dictionarySize;
printf("Please enter dictionary size\n");
scanf("%d", &dictionarySize);
char*** dictionary = MallocDic(dictionarySize);
int i;
for (i = 0; i < dictionarySize; i++) {
char* inputWord = (char*)malloc(WORDLEN * sizeof(char));
char* inputDef = (char*)malloc(DEFLEN * sizeof(char));
if (inputWord == NULL || inputDef == NULL)
{
printf("Failed to allocate memory!\n");
exit(1);
}
printf("enter word : \n");
scanf("%s", inputWord);
printf("enter definition : \n");
scanf("%s", inputDef);
printf("word : %s ,def : %s\n", inputWord, inputDef);
//dictionary[i] = MallocDicElement(inputWord, inputDef);
//free(inputDef);
free(inputWord);
}
printf("Print Dictionary : \n");
//PrintDictionary(dictionary, dictionarySize);
}
char*** MallocDic(int dictionarySize) {
char*** p;
p = (char***)malloc(dictionarySize * sizeof(char**));
return p;
}
char** MallocDicElement(char* word, char* definition) {
char** p = (char**)malloc(KEYVALUE * sizeof(char*));
int i;
for (i = 0; i < KEYVALUE; i++) {
if (i == 0) {
p[i] = (char*)malloc(WORDLEN * sizeof(char));
p[i] = word;
}
else {
p[i] = (char*)malloc(DEFLEN * sizeof(char));
p[i] = definition;
}
}
return p;
}
void PrintDictionary(char*** dictionary, int dictionarySize) {
int i = 0, j = 0;
for (i = 0; i < dictionarySize; i++) {
for (j = 0; j < KEYVALUE; j++) {
printf("word : %s\n", dictionary[i][0]);
printf("definition : %s\n", dictionary[i][1]);
}
}
}
The logic breaks in when trying to print the first string.
what am I missing here ?
Thanks for any help.
At least these problems.
Leaked memory
Code allocates memory and saves the pointer to that allocation to p[i] and then copies the pointer word to p[i] in the next line. This loses the pointer returned from malloc().
p[i] = (char*)malloc(WORDLEN * sizeof(char));
p[i] = word; // ???
Much more likely OP wants to copy the string, pointed to by word to the memory pointed to by p[i].
p[i] = malloc(WORDLEN);
strcpy(p[i], word);
More common to allocate only what is needed.
p[i] = malloc(strlen(word) + 1);
strcpy(p[i], word);
Research strdup().
Error checking omitted for brevity.
Do not use "%s", "%[]" without a width in *scanf()
Limit acceptable input to 1 less than the size of the destination array.
"%s" does not read and save spaces
The below will not work to read a definition that contains spaces.
printf("enter definition : \n");
scanf("%s", inputDef); // Stops after first word
Scanning will stop at the first white-space after reading some non-white-space.
Perhaps:
scanf(" %199[^\n]", inputDef);
Check return value of input functions
if (scanf(" %199[^\n]", inputDef) != 1) {
Handle_input_error();
}
Other:
Avoid hard to read & maintain allocation
Rather than cast (not needed) and size to the type (defined someplace else), allocate to the size of the referenced object - no type needed to get wrong.
// p = (char***)malloc(dictionarySize * sizeof(char**));
p = malloc(sizeof p[0] * dictionarySize);
Easier to code right, review and maintain.
At the risk of a non-answer here (not working with your extant code) I would like to suggest you take the time to better structure your data. Even something as simple as:
// A `dictionary` is an array of `capacity` entries, `size` of which are in use.
// Elements are kept in lexicographical order.
struct dictionary
{
struct entry
{
const char * word;
const char * definition;
};
struct entry * entries;
size_t size;
size_t capacity;
};
typedef struct dictionary dictionary;
This makes life about a bazillion times easier when dealing with stuff. You can now create a couple of useful functions:
dictionary * new_dictionary( size_t capacity );
void free_dictionary( dictionary * dict );
This structured nature makes it easier to manage individual parts. In particular, your users can pass the pointer to the dictionary around and never have to worry about it changing. For example, suppose you want to update the dictionary’s capacity:
void set_dicitionary_capacity( dictionary * dict, size_t new_capacity )
{
if (new_capacity < dict->size) return;
struct entry * new_entries = realloc( dict->entries, new_capacity * sizeof dict->entries[0] );
if (!new_entries) return;
dict->capacity = new_capacity;
dict->entries = new_entries;
}
This idea of having functions to interface with your opaque dictionary object is the basis for basic data encapsulation. Doing so makes the using code so much easier:
dictionary * words = new_dictionary( 1000 );
if (!words) fooey();
update_dictionary( words, "hello", "a greeting" );
update_dictionary( words, "world", "the Earth; a planet; any organism’s collective society" );
printf( "There are %zu words in the dictionary.\n", dictionary_size( words ) );
const char * desc = find_word( words, "there" );
printf( "Obi Wan can%s use this dictionary.\n", desc ? "" : "not" );
free_dictionary( words );
Hopefully we can already see how things are easier to grok on every level.
In other words, write code in such a way as to make meaning and structure as clear as possible. This helps to reduce the amount of failure our befuddled minds can generate when writing code.
I'm certain that I'm using pointer syntax incorrectly inside of my insertTowns function because when I try to run my file I just get a segmentation fault when I uncomment the lines involving pointers in that function. I know that I have the function set up right logically just not syntactically. What am I doing wrong in my pointer syntax for insertTowns?
To keep things simple, assume there is nothing wrong with FILE * infile and the arrays have been malloc'd correctly in a separate file. Also, length is initialized to 0 and then passed into the readFile function from main in another .c file. So it's not an array out of bounds problem.
I've watched numerous youtube videos on pointers (thenewboston had some good videos), looked at http://cslibrary.stanford.edu/106/ and a few other resources.
I've provide a snippet of my code below rather than the whole program to keep it simple since it's just a syntax problem:
typedef struct cityStruct { unsigned int zip; char * town; } city;
typedef struct zipTownsStruct {
int * zips; // indexs to main array cities sorted by zip
city * * towns; // pointers to main array cities sorted by town name
city * cities; // main array of cities in order from file not sorted
} zipTowns;
extern void insertTowns(zipTowns arrs, int * length) {
int j = (*length) - 1;
while (j >= 0 && ((strcmp(arrs.towns[j]->town, arrs.cities[*length].town)) > 0)) {
*arrs.towns[j + 1] = *arrs.towns[j];
j--;
}
*arrs.towns[j + 1] = arrs.cities[*length];
}
extern void readFile(zipTowns arrs, FILE * infile, int * length) {
char * zipCode;
char * town;
if((zipCode = malloc(sizeof(char) * 6)) == NULL) {
fprintf(stderr, "%s\n", strerror(errno));
exit(errno);
}
if((town = malloc(sizeof(char) * 26)) == NULL) {
fprintf(stderr, "%s\n", strerror(errno));
exit(errno);
}
while(fscanf(infile,"%s %s", zipCode, town) == 2) {
arrs.cities[*length].zip = atoi(zipCode);
arrs.cities[*length].town = town;
insertZips(arrs, length);
insertTowns(arrs, length);
(*length)++;
}
free(zipCode);
free(town);
}
in
extern void insertTowns(zipTowns arrs, int * length) {
int j = (*length) - 1;
while (j >= 0 && ((strcmp(arrs.towns[j]->town, arrs.cities[*length].town)) > 0)) {
*arrs.towns[j + 1] = *arrs.towns[j];
j--;
}
*arrs.towns[j + 1] = arrs.cities[*length];
}
if length is the number of entries of arrs.towns you start with j = (*length) - 1 so j+1 == *length and *arrs.towns[j + 1] access out of the array with undefined behavior. Probably the same in arrs.cities[*length], it seems also strange to copy always the same city.
In an array of length elements the valid indexes are 0 .. length-1
Warning
zipCode = malloc(sizeof(char) * 5)
allows to store zipcode of 4 characters max to have the place for the ending null character (in France zipcode uses 5 characters, may be not the case for you, but you do not give enough information allowing us to know)
It is difficult to say more because you do not give Minimal, Complete, and Verifiable example
This is part of an assignment, so the instructions are clear and I'm not allowed to use anything other than what is specified.
The idea is simple:
1) Create an array of structs which hold a string and a count
2) Count the occurrence of the string in each struct and store the count in that struct
3) Print the strings and their number of occurrences
I have been explicitly told to use the fgets and strstr functions
Here is what I've got so far,
#define MAX_STRINGS 50
#define LINE_MAX_CHARS 1000
int main(){
int n = argc - 1;
if (n > MAX_STRINGS) {
n = MAX_STRINGS;
}
Entry entries[MAX_STRINGS];
char **strings = argv+1;
prepare_table(n, strings, entries);
count_occurrences(n, stdin, entries);
print_occurrences(n, entries);
}
void prepare_table (int n, char **strings, Entry *entries) {
// n = number of words to find
// entries = array of Entry structs
for (int i = 0; i < n; i++){
Entry newEntry;
newEntry.string = *(strings + 1);
newEntry.count = 0;
*(entries + i) = newEntry;
}
}
void print_occurrences (int n, Entry *entries) {
for (int i = 0; i < n; i++){
printf("%s: %d\n", (*(entries + i)).string, (*(entries + i)).count);
}
}
void count_occurrences (int n, FILE *file, Entry *entries) {
char *str;
while (fgets(str, LINE_MAX_CHARS, file) != NULL){
for (int i = 0; i < n; i++){ // for each word
char *found;
found = (strstr(str, (*(entries + i)).string)); // search line
if (found != NULL){ // if word found in line
str = found + 1; // move string pointer forward for next iteration
i--; // to look for same word in the rest of the line
(*(entries + i)).count = (*(entries + i)).count + 1; // increment occurrences of word
}
}
}
}
I know for a fact that my prepare_table and print_occurrences functions are working perfectly. However, the problem is with the count_occurrences function.
I've been given a test file to run which just tells me that I'm not producing the correct output. I can't actually see the output to figure out whats wrong
I'm new to pointers, so I'm expecting this to be a simple error on my part. Where is my program going wrong?
fgets(char * restrict str, int size, FILE * restrict stream) writes into the buffer at str... but you don't have a buffer at str. What is str? It's just a pointer. What's it pointing at? Garbage, because you haven't initialized it to something. So it might work or it might not (edit: by which I mean you should expect it not to work, and be surprised if it did, thank you commenters!).
You could fix that by allocating some memory first:
char *str = malloc(LINE_MAX_CHARS);
// do your stuff
free(str);
str = NULL;
Or even statically allocating:
char str[LINE_MAX_CHARS];
That's one problem I can see anyway. You say you don't have output, but surely you can add some debug statements using fprintf(stderr, "") at the very least..?
I tried many solution for this issue, but none worked properly!
I want to copy value of char** array to a variable of type char*.
char *line;
char **tokens = malloc(....);
So, I tried the following:
for(i=0; i < sizeof(tokens); i++)
strncpy(line, tokens[i], strlen(line));
Or
for(i=0; i < sizeof(tokens); i++)
strncat(line, tokens[i]);
Or
for(i=0; i < sizeof(tokens); i++)
memcpy(line, tokens[i], strlen(line));
My understanding is that tokens[i] would be of type char*, but what I couldn't understand if the error I'm getting.
Segmentation fault (core dumped)
If these ways won't work, how can I do the copying?
Any hints?
char *removesubString(char *path, char **args){
char *dir;
int COUNT;
COUNT = 100;
char **dirs = malloc(sizeof(char*)*COUNT);
int i, position;
for (i = 2; i < sizeof(args); i++) {
if(args[i] == NULL){
break;
}
dir = strtok(path, PATH_DELIM);
position = 0;
while (dir != NULL) {
if(strcmp(dir, args[i]) == 0){
dir = strtok(NULL, PATH_DELIM);
continue;
}
dirs[position] = dir;
position++;
dir = strtok(NULL, PATH_DELIM);
}//end of while
dirs[position] = NULL;
}//end of for
char *line;
line = "";
for (i = 0; i < position; i++) {
strncpy(line, dirs[i], strlen(dirs[i]));
}
return line;
}
The first issue that pops up about your code is that you're wrong with the boundaries:
char *line;
char **tokens = malloc(TOKENS_ARRAY_SIZE);
when you do:
for(i=0; i < sizeof(tokens); i++) {
…
}
it's not returning the size of the allocated memory, but the allocated memory for the tokens pointer itself. From the sizeof manpage:
Returns the size, in bytes, of the object representation of type
It happens that when you do sizeof on a static matrix, it will return the size of the matrix because that's the amount of allocated memory for it. But for a dynamically allocated matrix, it will only return the size of the pointer, i.e. if you do:
char array_static[42];
char* array_dyn = malloc(sizeof(char)*42);
printf("sizeof(array_static) = %d\n", sizeof(array_static));
printf("sizeof(array_dyn) = %d\n", sizeof(array_dyn));
it will return:
sizeof(array_static) = 42
sizeof(array_dyn) = 8
so if the number of items within your dynamic array is less than the returned size of the array's pointer, you'll overflow and you'll get a segfault.
So the right way to handle your situation, is to keep the length of the dynamic array in another variable, update it as you're setting up the size of the allocated memory, and then use that value for iterations.
int tokens_length = 42;
char *line;
char **tokens = malloc(sizeof(char*)*tokens_length);
for(i=0; i < sizeof(tokens_length); i++) {
…
}
so in your case, you should be doing:
// keep somewhere the number of directories that you *can* allocate
int nb_dirs = 100;
char **dirs = malloc(sizeof(char*) * nb_dirs);
…
// keep a pointer on how many directories you've added
int position = 0;
while (dir != NULL) {
…
position++;
// fail loudly if you're adding more directories than you've allocated
// or you might use realloc() to extend the array's length
if (position >= nb_dirs) {
printf("ERROR! Too many directories!");
// RETURN WITH ERROR!
}
…
}
// here you iterate over all the directories you've added
for(i = 0; i <= position; i++){
// here you can do stuff with dirs, and copy only the length of the dirs element
strncpy(<TARGET>, dirs[i], strlen(dirs[i]);
}
Then there's another issue you should think about: in your loop, you're modifying path, given as an argument, where you're strcpy()ing dirs into:
strncpy(path, dirs[i], <LENGTH>);
But that makes little sense, whatever you're trying to do is not what you've written.
Here, considering that the size argument is correctly set, you'd be copying each item of the dirs array into the same variable. So you'd end up having always the last value of the dirs array referenced at the path pointer.
But the issue is that you only have the path pointer, but you know little about how it has been allocated when it's been given to the function. How has it been allocated, and how much memory was allocated? What "useful" size is it (though that one can be guessed with strlen())?
Oh, and finally, don't forget to free() your allocations once you're done with them. Do not leak memory, that's rude! ☺
edit:
ok, here are stuff I can see that are wrong, and some comments about it:
char *removesubString(char *path, char **args){
char *dir;
int COUNT = 100;
char **dirs = malloc(sizeof(char*)*COUNT);
int i, position;
/* for both XXX marks below:
*
* below, sizeof(args) will return the size of the pointer
* not the number of items it contains. You *NEED* to pass
* a "int argc" as parameter to your function, that gives
* the numbers of items in the array.
* Think about why you have argc in the main() function construct:
* int main(int argc, const char** argv)
* _OR_ if the args array of strings is _ALWAYS_ terminated
* by a NULL item, then you should do: */
// int i = 0;
// while(args[i] != NULL) {
// /* do stuff */
// ++i;
// }
for (i = 2; i < sizeof(args) /* XXX */; i++) {
if(args[i] == NULL){ /* XXX */
break;
}
dir = strtok(path, PATH_DELIM);
position = 0;
while (dir != NULL) {
if(strcmp(dir, args[i]) == 0){
dir = strtok(NULL, PATH_DELIM);
continue;
}
/* because within the function you have no guarantee
* on the number of tokens within path, if you have
* more than 100 tokens, you will overflow the dirs array.
* a good idea would be to test whether position is bigger
* than or equal to COUNT, and if it is use realloc to
* extend dirs */
dirs[position] = dir;
position++;
dir = strtok(NULL, PATH_DELIM);
/* you could avoid having twice the former line
* and instead make your loop body being: */
// while (dir != NULL) {
// if(strcmp(dir, args[i]) != 0){
// /* TODO: check position vs COUNT and realloc dirs if necessary */
// dirs[position] = dir;
// ++position;
// }
// dir = strtok(NULL, PATH_DELIM);
// }
}
dirs[position] = NULL;
}
char *line;
line = ""; /* ← here you allocate line with a string of length 1 */
for (i = 0; i < position; i++) {
// so here, you'll write up to the number of characters
// within dirs[i], into a string of length one.
strncpy(line, dirs[i], strlen(dirs[i]));
}
/* And even if it was working you'd be assigning the line
* variable to a new value at each iteration, ending up doing
* something equivalent to the following line, but with "position"
* numbers of iterations: */
// strncpy(line, dirs[position-1], strlen(dirs[position-1]));
/* Don't forget to free the instances you've allocated dynamically
* before leaving the function: */
// free(dirs);
/* And finally there's another issue here, you're returning
* a variable that has been statically allocated above, so that
* when you'll try to use the pointed instance in the calling
* context, that variable won't exist anymore. */
return line;
}
HTH
I have a fucntion which in it I want to return a string (i.e array of chars) with no spaces at all. This is my code, which in my understanding is not right:
char *ignoreSpace( char helpArr[], int length ){
int i = 0; int j = 0;
char withoutSpace[length];
while ( i < length ){
/*if not a space*/
if ( isspace( helpArr[i] ) == FALSE )
withoutSpace[j] = helpArr[i];
i++;
}
return *withoutSpace;
}
My intention in the line:
return *withoutSpace;
Is to return the content of the array withoutSpace so I could parse a string with no spaces at all.
Can you please tell me how can I make it any better?
Your current solution will lose the result of withoutSpace when the function returns as it is only defined in that function's scope.
A better pattern would be to accept a third argument to the function which is a pointer to a char[] to write the result into - in much the same way the standard functions do, (eg strcpy.
char* ignoreSpace(char* src, char* dst, int length) {
// copy from src to dst, ignoring spaces
// ...
// ...
return dst;
}
Try this (assuming null terminated string)
void ignoreSpace(char *str) {
int write_pos = 0, read_pos = 0;
for (; str[read_pos]; ++read_pos) {
if (!isspace(str[read_pos]) {
str[write_pos++] = str[read_pos];
}
}
str[write_pos] = 0;
}
You cannot return a pointer to a local variable from a function, because as soon as you leave the function all local variables are detroyed and no longer valid.
You must either
Allocate space with malloc in your function and return a pointer
to that allocated memory
not return a pointer from the function butmodify directly the
original string.
First solution :
char *ignoreSpace(char helpArr[], int length)
{
int i=0; int j=0;
char *withoutSpace = malloc(length) ;
while(i <= length)
{
/*if not a space*/
if(isspace(helpArr[i]) == FALSE)
withoutSpace[j++] = helpArr[i];
i++;
}
return withoutSpace;
}
Second solution:
char *ignoreSpace(char helpArr[], int length)
{
int i=0; int j=0;
while(i <= length)
{
/*if not a space*/
if(isspace(helpArr[i]) == FALSE)
helpArr[j++] = helpArr[i];
i++;
}
return helpArr;
}
There are some other small correction in my code. Finding out which ones is left as an exercise to the reader.
You don't increment j, ever. In the case that the current character of the source string is not a space, you probably would like to store it in your output string and then also increment the j by one; so that you'd store the next possible character into the next slot instead of overwriting the 0th one again and again.
So change this:
...
withoutSpace[j] = helpArr[i];
...
into this:
...
withoutSpace[j++] = helpArr[i];
...
And then also append your withoutSpace with a 0 or '\0' (they are the same), so that any string processing function may know its end. Also return the pointer, since you should do that, not the *withoutSpace or withoutSpace[0] (they are the same):
char *ignoreSpace( char helpArr[], int length ){
int i = 0; int j = 0;
char * withoutSpace = malloc( length * sizeof * withoutSpace ); // <-- changed this
while ( i < length ){
/*if not a space*/
if ( isspace( helpArr[i] ) == FALSE )
withoutSpace[j++] = helpArr[i]; // <-- replaced j with j++
i++;
}
withoutSpace[j] = 0; // <-- added this
return withoutSpace;
}
And then you should be good to go, assuming that you can have variable-length arrays.
Edit: Well, variable-length arrays or not, you better just use dynamic memory allocation by using malloc or calloc or something, because else, as per comments, you'd be returning a local pointer variable. Of course, this requires you to manually free the allocated memory in the end.