Spliting string and storing in array or pointer in C - arrays

I'm working in a little project, i have some names stored in a struct (example: Name1, Name2) and I need to split each one and store it in a array so I can call then each name separately (printf("%s", vet[1]) should print only "Name2").
This is my code:
int main(){
char temp[100];
LIGA *vetLiga;
int reference;
int quantiy;
separarEquipas(vetLiga, temp, reference, quantity);
}
int separarEquipas(LIGA *p, char vet[100], int vPesquisa, int n){
int i, nr, a;
char *ptr;
char *str;
for(i=0;i<n;i++){
if (p->id == vPesquisa){
nr = p->nrEquipas;
strcpy(str, p[i].eqLiga);
ptr = strtok(str, " ,");
while(ptr != NULL)
{
vet[a++] = ptr; //here I'm trying to store each word in a position of the array
ptr = strtok(NULL, " ,");
}
}
p++;
}
return nr;
}
The issue is inside the while where I try to store each token in the array but it keeps crashing the terminal. I tried in different ways like using strcpy and memcpy as other posts suggest but nothing :(.
Some errors that i got while trying to find a solution:
[Warning] assignment makes integer from pointer without a cast;
[Warning] passing argument 1 of 'strcpy' makes pointer from integer without a cast.
Hope you can help me,
Thank you!

You didn't post the full code, so from what I can see vetLiga that in separarEquipas becomes p is uninitialised.
Another issue is that you try to use str in strcpy without allocating memory for it. You need to do that
char *str = malloc( max_number_of_characters_in_str );
Then here:
vet[a++] = ptr; //here I'm trying to store each word in a position of the array
You are doing exactly what you said in the comment. However you can't store a word into the space for a single character. vet needs to be a 2D array or if you want even an array of pointers to char.
If you want further help include the whole program.

In main, vetLiga is never assigned a value, but maybe you abbreviated the code.
In separarEquipas you have the following:
char *str;
strcpy(str, p[i].eqLiga)
So you are copying a string to a random location in memory.

Related

get updated value from string pointer C

tearing my hair out over C strings over here. I have a function in a project which returns a char * pointer.
I need to change an element of that string before using it. Everything I read says just use a char array with the char[] format, but this is not compatible with my project in its current state, if at all.
I have desperately been looking for someway to copy the first n characters to a second char pointer, add the updated value and then concat the remainder of the initial pointer (minus the original value that was updated) that doesnt take 40 lines of code.
Every attempt to use fgetc for this has failed to write the unsigned int to the 'updated pointer'. Do I need to sprintf the unsigned int into a char buffer or something? why does this feel so ridiculously complicated?
An example of a failed attempt at the first steps of the desired behavior:
int main() {
char *s;
s = "babado = lubidee = popop =pew";
char * s1;
s1 = malloc(10);
memset(s1,'0',9);
strcpy(s1,fgetc(s));
for (int i = 0; i<4; i++){
strcat(s1,fgetc(s));
}
printf("%s",s1);
return 0;
}
If you need to just copy a string to another pointer,
.
.
char *newptr;
//Allocate memory for new pointer
int i=0;
while(i<n) //first n characters
*(newptr+i)=*(returnedptr+i);. //returnedptr is your initial ptr
//Add new value
i++;
while( *(returnedptr+i)!='\0')
*(newptr+i)=*(returnedptr+i);
.
.

How do I receive a char array in a C function?

I wish to split a "string" by the character ','.
The string holds a GPS NMEA encoded string, but that is of no matter.
My problem is that sometimes the parameter from the function that processes this char array is empty... Like nothing is in the array.
How should I correctly pass a "char string[]" to a function so that I may operate on a that parameter as I sent it(as a char array, not a char pointer to an array).
I also need to specify that I'm using mikroC for PIC.
Here is my code as of right now:
char* GPS_sateliti;
char CsatInView[] =
"$GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*74";
GPS_sateliti = GrupeazaDupaVirgule(CsatInView, 2);
char* GrupeazaDupaVirgule( char deGasit[],int nrVirgule ){
int cVirgule = 1;
char* pch = strtok (deGasit,",");
while (pch != 0)
{
pch = strtok (0, ",");
cVirgule++;
if(nrVirgule == cVirgule){
break;
}
}
return pch;
}
The function that operates on the char array received as a parameter in debug mode, before entering the function the char array is fine, after entering it, it seems to be empty
It may be that I should receive a pointer to an array of chars??
Any sort of advice is welcome.
Thank you
How should I correctly pass a "char string[]" to a function so that I may operate on a that parameter as I sent it(as a char array, not a char pointer to an array).
You can't. A function parameter of an array type always decays as the corresponding pointer type.
There are two idiomatic solutions to this.
1. a sentinel:
The last value in the array is a special value that marks the end. This is done in C with strings. They always end with a \0 character, that is guaranteed not to occur inside the string. The function can search for that character to know where the data ends.
(Note: with this info I have to add I'm not sure what your problem is. If you pass an "empty string", as literally "", the \0 will be there, so you shouldn't have a problem)
2. explicitly passing the size:
instead of just
void foo(int bar[]);
you define a function
void foo(size_t barSize, int bar[]);
The caller knows the size of the array, so it can just pass it along.
With a pointer :
char* arr;
yourFunction(arr);
If you wish to initialize it before :
char* arr = malloc(51 * sizeof(char)); // Allocate a memory place of 50 because strings are null terminated in C
yourFunction(arr);
An other way to allocate memory to an array :
char* arr = calloc(50, sizeof(char)); // Allocate 50 memory place which size if the size of a char
With a string :
char arr[50];
char* ptr = arr;
yourFunction(ptr);
You have to know that it is impossible in C to know the size of an array when using pointer. The only thing you can do is to parse the size of the string as a parameter :
size_t size = 50;
char arr[size];
char* ptr = arr;
yourFunction(ptr, size);
If you wish to understand in detail how pointer works and how to iterate them, may be this post can help you. I think it is very interesting.
Globally, you iterate through an array via a pointer like this :
for ( int i = 0; i < size; i++)
printf("Current pointed value in the array : %c\n", ptr[i]); // or arr[i]
I guess you understand why giving the size of a pointed array as a parameter is important. Sometimes you can avoid using this parameter like this :
for ( int i = 0; i != '\0'; i++) // Because strings are null-terminated in C.
// Do something

Using pointers to iterate over strings

I have a string
char *str = "hello world";
I also have a int pointer
int *ptr;
How can I use these two in a function that loops over the string and prints all the chars in it?
The header function would be something like this:
void print(const int *ptr){
while(*ptr != 0){
printf("%c", (char)*ptr);
++ptr;
}
}
Now I know that I want to use the ptr to somehow reference the char ptr. But how would I do this?
I've tried doing just
ptr = str;
And tried a whole bunch of different combinations of
ptr=*str;
ptr=&str;
And so on.
I know I can iterate over the string just doing
while(*str != 0){
printf("%c",*str)
str++;
}
And that I can also do it using index elements like str[0].
But how can I use a pointer to act as the index element for the char string?
Why do you need to use int * to access char *? It is not correct and shouldn't be done so.
The main problem with it is that each time you increase you pointer ptr by 1 it is incremented by sizeof(int) bytes (which is platform dependent and varies between 2 and 4). While each character in the string is of size 1 byte.
Also when you write *ptr you actually access sizeof(int) bytes which may result in segmentation fault if ptr points to the end part of the string.
If you have no option to change the function signature do it like this:
void print(const int *ptr){
const char* char_ptr = (const char*)ptr;
while(*char_ptr != 0){
printf("%c", *char_ptr);
++char_ptr;
}
}
If all you need is just to print the string to which (for some reason) const int* ptr is pointing then you can do something like that:
void print(const int *ptr)
{
printf("%s", ptr);
}
printf won't check the type of the pointer, it will assume that the pointer is pointing to a buffer of chars and will print the whole buffer until it reachs '\0'.

C programming strcat using pointer

I am a beginner in C. I wanted to make strcat function using pointers. I made it but don't know what is wrong with it. I used gcc compiler and it gave segmentation fault output.
#include<stdio.h>
#include<string.h>
char scat(char *,char *);
void main()
{
char *s="james";
char *t="bond";
char *q=scat(s,t);
while(*q!='\0') printf("the concatenated string is %c",*q);
}
char *scat(char *s,char *t)
{
char *p=s;
while(*p!='\0'){
p++;
}
while(*t!='\0'){
*p=*t;
p++;
t++;
}
return p-s-t;
}
This one works:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *scat(char *,char *); /* 1: your prototype was wrong */
void main()
{
char *s="james";
char *t="bond";
char *q=scat(s,t);
printf("cat: %s\n", q); /* 2: you can use %s to print a string */
free(q);
}
char *scat(char *s,char *t)
{
char *p=malloc(strlen(s)+strlen(t)+1); /* 3: you will have to reserve memory to hold the copy. */
int ptr =0, temp = 0; /* 4 initialise some helpers */
while(s[temp]!='\0'){ /* 5. use the temp to "walk" over string 1 */
p[ptr++] = s[temp++];
}
temp=0;
while(t[temp]!='\0'){ /* and string two */
p[ptr++]=t[temp++];
}
return p;
}
You have to allocate new space to copy at the end of s. Otherwise, your while loo[ will go in memory you don't have access to.
You shoul learn about malloc() here.
It is undefined behaviour to modify a string literal and s, and eventually p, is pointing to a string literal:
char* s = "james";
s is passed as first argument to scat() to which the local char* p is assigned and then:
*p=*t;
which on first invocation is attempting to overwite the null character an the end of the string literal "james".
A possible solution would be to use malloc() to allocate a buffer large enough to contain the concatentation of the two input strings:
char* result = malloc(strlen(s) + strlen(p) + 1); /* + 1 for null terminator. */
and copy them into it. The caller must remember to free() the returned char*.
You may find the list of frequently asked pointer questions useful.
Because p goes till the end of the string and then it starts advancing to illegal memory.
That is why you get segmentation fault.
It's because s points to "james\0", string literal & you cannot modify constant.
Change char *s="james"; to char s[50]="james";.
You need to understand the basics of pointers.
a char * is not a string or array of characters, it's the address of the beginning of the data.
you can't do a char * - char* !!
This is a good tutorial to start with
you will have to use malloc
You get a segmentation fault because you move the pointer to the end of s and then just start writing the data of p to the memory directly following s. What makes you believe there is writable memory available after s? Any attempt to write data to non-writable memory results in a segmentation fault and it looks like the memory following s is not writable (which is to expect, since "string constants" are usually stored in read-only memory).
Several things look out of order.
First keep in mind that when you want to return a pointer to something created within a function it needs to have been malloc'ed somewhere. Much easier if you pass the destination as an argument to the function. If you follow the former approach, don't forget to free() it when you're done with it.
Also, the function scat has to return a pointer in the declaration i.e. char *scat, not char scat.
Finally you don't need that loop to print the string, printf("%s", string); will take care of printing the string for you (provided it's terminated).
At first, your code will be in infinte loop because of the below line. you were supposed to use curely braces by including "p++; t++ " statements.
while(*t!='\0')
*p=*t;
though you do like this, you are trying to alter the content of the string literal. which will result in undefined behavior like segmentation fault.
A sequence of characters enclosed with in double quotes are called as string literal. it is also called as "string". String is fixed in size. once you created, you can't extend its size and alter the contents. Doing so will lead to undefined behavior.
To solve this problem , you need to allocate a new character array whose size is sum of the length of two strings passed. then append the two strings into the new array. finally return the address of the new array.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* scat(char *,char *);
void append(char *t , char *s);
int main(void)
{
char *s="james";
char *t="bond";
char *n = scat(s,t);
printf("the concatenated string is %s",n);
return 0;
}
char* scat(char *s,char *t)
{
int len = strlen(s) + strlen(t);
char *tmp = (char *)malloc(sizeof(char)* len);
append(tmp,s);
append(tmp,t);
return tmp;
}
void append(char *t , char *s)
{
//move pointer t to end of the string it points.
while(*t != '\0'){
t++;
}
while( *s != '\0' ){
*t = *s;
t++;
s++;
}
}

Structs, strtok, segmentation fault

I'm trying to make a program with structs and files. The following is just a part of my code(it;s not the entire program).
What i'm trying to do is: ask the user to write his command. eg. delete John
eg. enter John James 5000 ipad purchase.
The problem is that I want to split the command in order to save its 'args' for a struct element. That's why i used strtok. BUT I'm facing another problem in who to 'put' these on the struct.
Also it's seems quite odd to me how to 'pass' the 'args' to the struct in a safe way,as I save all enters (from user) on a binary file which maybe be reopened and rewrited so I cant use :
strcpy(catalog[0]->short_name, args[1]);
Because it's time the short name will be saved in the first element of the struct. But if the file is written what happens then? The first element exists so if i write ..[0] i will write up on it?
What should I do? Thanx in advance for any help! :D
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
char command[1500];
struct catalogue
{
char short_name[50];
char surname[50];
signed int amount;
char description[1000];
}*catalog[MAX];
int main ( int argc, char *argv[] )
{
int i,n;
char choice[3];
printf(">sort1: Print savings sorted by surname\n");
printf(">sort2: Print savings sorted by amount\n");
printf(">search+name:Print savings of each name searched\n");
printf(">delete+full_name+amount: Erase saving\n");
printf(">enter+full_name+amount+description: Enter saving \n");
printf(">quit: Update + EXIT program.\n");
printf("Choose your selection:\n>");
gets(command); //it save the whole command
/*in choice it;s saved only the first 2 letters(needed for menu choice again)*/
strncpy(choice,command,2);
choice[2]='\0';
char** args = (char**)malloc(strlen(command)*sizeof(char*));
memset(args, 0, sizeof(char*)*strlen(command));
char* temp = strtok(command, " \t");
for (n = 0; temp != NULL; ++n)
{
args[n] = strdup(temp);
temp = strtok(NULL, " \t");
printf(" %s ",args[n]);
}
strcpy(catalog[0]->short_name, args[1]); //segmentation fault
strcpy(catalog[0]->surname,args[2]);
catalog[0]->amount=atoi(args[3]); //atoi doesn't work
strcpy(catalog[0]->description,args[4]);
}
As a result, after running the program i get a Segmentation Fault...
for the line:
strcpy(catalog[0]->short_name, args[1]);
Any help? Any ideas?
You have 2 errors:
Your catalog[MAX] array holds MAX pointers to your struct catalogue, but none of them are initialized. The way to fix this is to either not declare them to be pointers, or to malloc them as needed, like in catalog[0] = (struct catalogue *)malloc(sizeof(struct catalogue));
Your args variable is bad. First, I don't think you intend to create an array of strings whose length is the length of your command string. That means if you type "sort1" you will create args[5]. That's nonsensical, because the length of your command has nothing to do with how many arguments it should have.
But assuming you really want to do that, you are creating space for the array, but not for the strings within the array. You will get a segfault eventually anyway (though the one you are getting is due to #1 above) because of that. You need to allocate space for each element in args as you use it.
The code could look like this:
for (n = 0; temp != NULL; ++n)
{
args[n] = (char *)malloc((strlen(temp) + 1) * sizeof(char));
strcpy(args[n], temp);
// and so on
}
The for loop assigns one argument at a time (args[n] = ...), but then accesses several arguments on each pass: *args[1], args[2], etc., which are uninitialized on the first pass.
The warning is due to another bug. You can't just assign a pointer to an array like that. Use strcpy() instead.
your array for catalouge is an array of pointers, not an array of objects, but those pointers aren't initialized to anything, hence the seg fault
try:
struct catalogue
{
char short_name[50];
char surname[50];
signed int amount;
char description[1000];
}catalog[MAX];
strcpy(catalog[0].short_name, args[1]); //segmentation fault
strcpy(catalog[0].surname,args[2]);
catalog[0].amount=atoi(args[3]); //atoi doesn't work
strcpy(catalog[0].description,args[4]);
Lots of problems in this code.
First of all, you're confusing the number of arguments on the input line for the number of entries in the catalog. In one context you're using n to count the number of args, but in another you're using it to index the catalog array.
You're creating memory management headaches where you don't need to. The args variable is completely unnecessary, and you're allocating the memory for it incorrectly anyway. You're basically saying, "allocate a pointer to char for every character in command, which is probably not what you want.
Lose args completely; you don't need it.
I realize this is not your entire program, but it's not clear why you're creating catalog as an array of pointer to struct catalog as opposed to just a regular array.
I'm not sure what you think you're doing on the line
*catalog[n]->short_name=*args[1];
The type of the expression catalog[n]->short_name is char[50]. In this context the array type is implicitly converted ("decays") to a pointer type, char *. Thus the type of the whole expression *catalog[n]->short_name is * (char *), or just plain char, which is an integral type. You're essentially trying to assign the value of the first character of args[1] to the first character of catalog[n]->short_name.
None of this matters anyway, because catalog[n] hasn't been initialized to point anywhere meaningful; the segfault is coming from the attempt to access the short_name member, which implicitly dereferences catalog[n], which is pointing somewhere random.
Next, you cannot use the assignment operator = to assign string data; you must use strcpy() or strncpy() to do that.
Finally, NEVER NEVER NEVER NEVER NEVER use gets(). It will introduce a point of failure in your code. It has been officially deprecated in C99 and should no longer be used. Use fgets() instead:
if (fgets(command, sizeof command, stdin) != NULL)
{
char *newline = strchr(command, '\n');
if (newline != NULL)
*newline = 0;
}
Here's the way you need to parse out the command string and assign the fields to members of the struct:
curToken = strtok(command, '\t');
if (curToken)
strncpy(catalog[n]->short_name, curToken, sizeof catalog[n]->short_name);
curToken = strtok(NULL, '\t');
if (curToken)
strncpy(catalog[n]->surname, curToken, sizeof catalog[n]->surname);
curToken = strtok(NULL, '\t');
if (curToken)
{
char *chk;
catalog[n]->amount = (int) strtol(curToken, &chk, 10);
if (!isspace(*chk) && *chk != 0)
fprintf(stderr,
"Warning: expected integer value for amount, received %s instead\n",
curToken);
}
curToken = strtok(NULL, '\t');
if (curToken)
strncpy(catalog[n]->description, curToken, sizeof catalog[n]->description);
This code assumes that catalog is still being declared as an array of pointer and that each element has been initialized to point somewhere meaningful. Otherwise change the declaration from struct catalog {...} *catalog[MAX]; to struct catalog {...} catalog[MAX] and change -> to ..

Resources