So, I've been working on implementing this struct for a String. However, I keep on getting a Segmentation Fault when calling *createString();
Here us the .h contents
typedef struct {
char *characters;
int length;
} String;
String *createString();
Here is the implementation in my .c file
String *createString(){
char *m,b;
int n = 0;
String *theS = (String *) malloc (sizeof(String));
m = theS->characters;
b = getchar();
while((b = getchar()) != '\n'){
*(m+n) = b;
n++;
m = realloc(m, n+1);
}
*(m+n) = '\0';
theS->length = strlen(theS->characters);
return new;
}
Problem 1
Q: after this line:
String *theS = (String *) malloc (sizeof(String));
what does theS->characters point to?
A: Who knows? Nowhere useful, though.
You'll need to allocate at least a character, to hold the '\0' that eventually gets inserted.
String *theS = malloc (sizeof(String));
theS->characters = malloc(1);
Problem 2
You then modify m all over the place, but never reassign that value to theS->characters, so when you say
theS->length = strlen(theS->characters);
that's not going to be a very helpful answer.
Right before that line, add:
theS->characters = m;
Problem 3
return new;
should probably be:
return theS;
Problem 4
You're throwing away the first character. Just remove the standalone b = getchar(); line.
Working example:
https://ideone.com/tm1TG9
As #HuStmpHrr suggests: when you allocate your String, you don't allocate any space for its characters field to point to, so when you try to access what it points to, things will go bad.
Using your style and not checking allocation errors:
String *createString(){
int n = 0;
char *m = malloc(1);
int c;
String *theS = (String*)malloc(sizeof(String));
while ((c = getchar()) != EOF && c != '\n') {
m = realloc(m, n + 2);
m[n] = c;
n++;
}
m[n] = '\0';
theS->characters = m;
theS->length = n;
return theS;
}
Related
I am trying to write a program that reads input and prints it with 60 characters each line, with a pointer to store the characters.
And I always get segmentation fault when entering a lot of characters, and I think the realloc() cause it but I can't figure out why.
This is my code (a little long but if someone can help me I will be thankful):
Ignore the empty functions.
int main() {
int opt;
char *p;
int checkRead = -1;
p = (char*) calloc(60,1);
scanf("%d",&opt);
checkRead = readText(opt,p);
if (!checkRead) {
}
int readText(int opt, char *p) {
switch(opt) {
case dynamicList:
return dynamicReadText(p);
return 1;
}
int dynamicReadText(char *p) {
register int i;
int ch;
char *checker = NULL;
fflush(stdin);
for (i = 0; (ch = getchar()) != EOF; i++) {
if (i >= 60 && i % 60 == 0) {
checker = (char*)realloc(p,i+60);
if (!*(checker)) {
return 0;
}
p = checker;
free(checker);
checker = NULL;
*(p+i) = '\n';
i++;
}
if (ch == '\n') {
i--;
}
else {
*(p+i) = ch;
}
}
*(p+i) = '\0';
return 1;
}
The problems are numerous.
checker = (char*)realloc(p,i+60);
if (!*(checker))
should be
checker = (char*)realloc(p,i+60);
if (!checker)
You want to check if the value returned by realloc is NULL. You are instead checking if the first character of the memory block is zero.
This second problem is the probably the one leading to the SIGSEGV.
Select lines of your code:
char *checker = NULL;
checker = (char*)realloc(p,i+60); // Allocates a memory block.
p = checker; // Both p and checker points to this block.
free(checker); // The block is freed.
*(p+i) = '\n'; // XXX Derefs a pointer pointing to freed memory.
Finally, you are changing the dynamicReadText's p with the expectancy that this will change the p in readText. Similarly, you expect that changing readText's p will change main's. But these are entirely different variables. C always passes by value.
Well, I said finally, but only in the sense that this is the extent of what this answer covers. I haven't established that there are no other problems.
All together, your code should look something like this:
int f(char **p_ptr) {
...
while (...) {
...
char* tmp = realloc(*p_ptr, ...);
if (!tmp) {
...
}
*p_ptr = tmp;
...
}
...
}
int main(void) {
char *p = NULL;
f(&p);
...
free(p);
}
I had this problem for a while. I cannot create a gets(int maxChar) function that allows the user to get a char* using a get_char() function.
My current code:
char* gets(int maxChar) {
char a;
char* b;
int i;
for(i = 0; i<maxChar; i = i + 1){
a = getchar();
if (a != 0x0D) {putchar(a);} else {puts("\r\n");break;}
b[sizeof(b)] = a;
}
if (sizeof(b) > maxChar-1) {puts("\r\n");}
return b;
//if (b[sizeof(b)-1] != '')
}
the get_char() function works perfectly.
Full kernel.c: https://pastebin.com/3bqTbHsv
Change
char* b;
to
char* b = (char *)malloc(maxChar);
and
b[sizeof(b)] = a;
to
b[i] = a;
Also, change
if (sizeof(b) > maxChar-1) {puts("\r\n");}
to
if (i > maxChar-1) {puts("\r\n");}
The changes made are:
You have created a pointer, but have not allocated any memory. Hence the malloc statement.
sizeof(b) will always be 4 for a 32-bit compiler. You need the array index, given by i.
Same as 2.
These are the basic changes you need to make, without any change to your logic.
The following is an educated guess at what you were attempting to do. It includes some explanations, and a calling example:
char* _gets(int maxChar) // change name to avoid conflict with library 'gets'
{
//char a; //addresses concern pointed out in comments.
int a; //variable is used by function that can return EOF (-1)
int i=0; //
char* b = calloc(maxChar + 1, 1);//point pointer to memory (that it owns)
if(b) //test for success before going on
{
for(i = 0; i<maxChar-3; i = i + 1) // -3 to leave room for \r\n\0
{
a = getchar();
if ((a != 0x0D) && (a != EOF))
{
putchar(a);
b[i]=a;// place char into string accumulator
}
else break;// either EOF or <ENTER> occurred
} // no need for else in this implementation as we can handle
// the clean up once the conditions are met by outputting
// user's entries, then preparing your string (array) for return
puts("\r\n");
b[i++]='\r';
b[i++]='\n';
b[i++]='\0';
}
else return NULL;//failed to allocate memory. leave
return b; // return b (now a string)
//if (b[sizeof(b)-1] != '') // not sure what this was for
}
int main(void)
{
char *strArray = _gets(10);//creates memory for strArray
if(strArray) //use only if not NULL
{
printf("The array contains: %s", strArray );
free(strArray );
}
return 0;
}
I got the following string from the user:
char *abc = "a234bc567d";
but all the numbers can have different lengths than in this example (letters are constants).
How can I get each part of numbers? (again, it can be 234 or 23743 or something else..)
I tried to use strchr and strncpy but I need to allocate memory for this (for strncpy), and I hope there is a better solution.
Thanks.
You can do something like this:
char *abc = "a234bc567d";
char *ptr = abc; // point to start of abc
// While not at the end of the string
while (*ptr != '\0')
{
// If position is the start of a number
if (isdigit(*ptr))
{
// Get value (assuming base 10), store end position of number in ptr
int value = strtol(ptr, &ptr, 10);
printf("Found value %d\n", value);
}
else
{
ptr++; // Increase pointer
}
}
If I understand your question, you are trying to extract the parts of the user input that contain numbers ... and the sequence of numbers can be variable ... but the letters are fixed i.e. a or b or c or d. Correct ... ? The following program may help you. I tried it for strings "a234bc567d", "a23743bc567d" and "a23743bc5672344d". Works ...
int main()
{
char *sUser = "a234bc567d";
//char *sUser = "a23743bc567d";
//char *sUser = "a23743bc5672344d";
int iLen = strlen(sUser);
char *sInput = (char *)malloc((iLen+1) * sizeof(char));
strcpy(sInput, sUser);
char *sSeparator = "abcd";
char *pToken = strtok(sInput, sSeparator);
while(1)
{
if(pToken == NULL)
break;
printf("Token = %s\n", pToken);
pToken = strtok(NULL, sSeparator);
}
return 0;
}
Hi I am kind of new to pointers and I am trying write a function that switches one string with another without using any array notation, so completely with pointers.
I have got this function, which works, but in this one, I use one array notation.
Is there an easier, better way to do this? Thank you.
void stringtausch(char *eins, char *zwei) {
char first[50], *philfe = first, *one = eins, *two = zwei;
while(*one != '\0') {
*philfe++ = *one++;
}
*philfe = '\0';
while(*two != '\0') {
*eins++ = *two++;
}
*eins = '\0';
philfe = first;
while(*philfe != '\0') {
*zwei++ = *philfe++;
}
*zwei = '\0';
}
If both strings have equal length
void stringtausch(char *eins, char *zwei) {
while ((*eins != '\0') && (*zwei != '\0')) {
char swp;
swp = *zwei;
*zwei++ = *eins;
*eins++ = swp;
}
*zwei = '\0';
*eins = '\0';
}
if they don't it's not possible unless you allocate enough space before passing the pointers. And I don't see much benefit in that since you can
void stringtausch(char **eins, char **zwei) {
char *swp;
swp = *zwei;
*zwei = *eins;
*eins = swp;
}
and call stringtausch
stringtausch(&s1, &s2);
Well an easier way is to use strcpy, but if you want to do your way, it's much easier. A pointer points to the first cell address of an array or single cell. You can merely just do this:
char * eins = "dogslovecats";
char * zwei = "cats";
stringtausch(&eins, &zwei);
void stringtausch(char ** eins, char ** zwei) {
char * temp;
temp = *eins;
*eins = *zwei;
*zwei = *temp;
}
I'm making a raytracing engine in C using the minilibX library.
I want to be able to read in a .conf file the configuration for the scene to display:
For example:
(Az#Az 117)cat universe.conf
#randomcomment
obj:eye:x:y:z
light:sun:100
light:moon:test
The number of objects can vary between 1 and the infinite.
From now on, I'm reading the file, copying each line 1 by 1 in a char **tab, and mallocing by the number of objects found, like this:
void open_file(int fd, struct s_img *m)
{
int i;
char *s;
int curs_obj;
int curs_light;
i = 0;
curs_light = 0;
curs_obj = 0;
while (s = get_next_line(fd))
{
i = i + 1;
if (s[0] == 'l')
{
m->lights[curs_light] = s;
curs_light = curs_light + 1;
}
else if (s[0] == 'o')
{
m->objs[curs_obj] = s;
curs_obj = curs_obj + 1;
}
else if (s[0] != '#')
{
show_error(i, s);
stop_parsing(m);
}
}
Now, I want to be able to store each information of each tab[i] in a new char **tab, 1 for each object, using the ':' as a separation.
So I need to initialize and malloc an undetermined number of char **tab. How can I do that?
(Ps: I hope my code and my english are good enough for you to understand. And I'm using only the very basic function, like read, write, open, malloc... and I'm re-building everything else, like printf, get_line, and so on)
You can't allocate an indeterminate amount of memory; malloc doesn't support it. What you can do is to allocate enough memory for now and revise that later:
size_t buffer = 10;
char **tab = malloc(buffer);
//...
if (indexOfObjectToCreate > buffer) {
buffer *= 2;
tab = realloc(tab, buffer);
}
I'd use an alternative approach (as this is c, not c++) and allocate simply large buffers as we go by:
char *my_malloc(size_t n) {
static size_t space_left = 0;
static char *base = NULL;
if (base==NULL || space_left < n) base=malloc(space_left=BIG_N);
base +=n; return base-n;
}
Disclaimer: I've omitted the garbage collection stuff and testing return values and all safety measures to keep the routine short.
Another way to think this is to read the file in to a large enough mallocated array (you can check it with ftell), scan the buffer, replace delimiters, line feeds etc. with ascii zero characters and remember the starting locations of keywords.