Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.
"The strsep() function locates, in the string referenced by *stringp, the first occurrence of any character in the string delim (or the terminating `\0' character) and replaces it with a `\0'. The location of the next character after the delimiter character (or NULL, if the end of the string was reached) is stored in *stringp. The original value of *stringp is returned."

Is not the "original value of *stringp" what I am trying to get? If it is not, what is the purpose of strsep?
 
Look at the example here:
http://www.delorie.com/djgpp/doc/libc/libc_773.html

It is used to "iterate" through the tokens of a string. That is not what you want to do here. It might be easier to do:
Code:
if(strlen(string) > 0) {
  if(string[strlen(string)-1] == ';') string[strlen(string)-1] = '\0';
}

It may be helpful to explain to us in more detail what this project is doing, and what you're hoping to achieve, as well as the level of programming proficiency you have. If you are not at the point that you understand what man pages are saying, we need to know that to give you a more thorough explanation. If this is a school project, you need to say so so we don't do your homework for you. If this is just to "get it to work" we will guide you differently than if you are doing this for practice to learn how to code or a new language.

-Lee
 
This is in the description: "replaces it with a `\0'". What is the purpose of this if the "the location of the next character after the delimiter character is stored in *stringp"? So that the original string, that has the delimiter, is returned, and *stringp's original value is overwritten with the location of the next string after the delimiter. Where does the string with the \0 in place of the delimiter go?
 
The return value will be to the base of the original string, which will now be terminated at the point where the first delimiter was found. *stringp has the address of the character right after that delimiter, basically "the rest" of the string. When called again the next delimiter is found, replaced with '\0', and *stringp is "advanced" again to the position immediately following the delimiter. This allows you to advance through a string. Compile and run this, and observe the output.

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

int main(int argc, char *argv[]) {
	char *string,*tmp;
	string = calloc(200,sizeof(char));
	strcpy(string,"1234.32;12343.43;12324.4;3235.3");
	printf("Original address of string: %p\n",string);
	char **strptr = &string;
	while(tmp = strsep(strptr,";")) {
		printf("string: %p :: %s\n",string,string);
		printf("tmp: %p :: %s\n\n",tmp,tmp);
	}
}

-Lee
 
The description just says "The original value of *stringp is returned", not "The base of the original string which will now be terminated at the point where the first delimiter was found is returned", which it should.
Anyway, if that is the case, why can
Code:
	char string[10];
	string = strsep(NULL, ";");
not be used to remove the delimiter? It produces "incompatible types in assignment".
 
They are the same. The man page might be more concise, but the meaning is the same.

You cannot assign to a statically allocated array. strsep returns a char *, string is a char[]. Think of it like this:
Code:
int main(int argc, char *argv[]) {
	char string[100];
	string = "1234";
}

You get the same error when trying to compile.

Did you run the code I posted? If not it might be instructive to do so. Seeing what's happening with the various pointers involved might help you understand why what you're trying is failing. I also posted code above that will work fine for chomping off trailing ';'s. You could also write a very short function to trim off the last character of any string if you find you need to do so often.

-Lee
 
Anyway, if that is the case, why can
Code:
	char string[10];
	string = strsep(NULL, ";");
not be used to remove the delimiter? It produces "incompatible types in assignment".

That code won't compile because you can't assign another value to string. Declared arrays cannot be reassigned. They are effectively constants.

Also, passing NULL as the first argument to strsep has no possibility of working. It simply makes no sense at all.

Considering all the posts you've made in this thread, you seem to have an inadequate understanding of pointers. That's the one underlying theme that ties together every problem you've posted. Until you address this fundamental problem, you will continue to have problems whenever pointers are involved.
 
I got the desired result using
Code:
if(strlen(string) > 0) {
  if(string[strlen(string)-1] == ';') string[strlen(string)-1] = '\0';
}
However, I want to know why using strsep does not work.
Using char *string instead of char string[10] helped, as it removed the error, but now I get EXC_BAD_ACCESS. What is the problem?
Code:
	char *string;
	fscanf(fp, "%s", string);
	string = strsep(&string, ";");
So neither char *string or char string[] works, as both produce errors.
 
What is the problem?

As chown33 stated, the problem is that you don't understand pointers.

The technical problems with that code (which I still can't compile) are:
string is an uninitialized pointer. There is not usable memory on the other end of it to read into.

&string will work if it points to a char * that is modifiable, which points to memory which is modifiable.

strsep is by no means the right way to remove a character from the end of a string. I posted 3 lines of code above that will check if the last character of a string is a ; and will replace it with '\0' if it is.

-Lee

Edit: in your edit you added that you tried the code I posted above. It works because it suits the problem, while strsep does not. It iterates through a string modifying the contents and the pointer passed in to facilitate doing so. Did you run the strsep code I posted to see how it works?
 
Thanks. I actually understand pointers, but I did not understand strsep and declared arrays properly. Could you also answer this question: I have a list of floats in a text file and want to get them one line at a time. fscanf stops at whitespaces so how to know when there is a carriage return?
 
I tried to use getline but it does not seem to be supported by gcc.
 
I tried to use getline but it does not seem to be supported by gcc.

getline is a c++ function to use it you can do like this:

Code:
#include <iostream>

int main()
{
        char str[256];
        std::cin.getline(str, 256);
        std::cout << str << std::endl;

        return 0;
}

But for a c equivalent use fgets. The only anoying thing about fgets is that you need to strip of the newline as it becomes part of the string.

Code:
#include <stdio.h>

int main()
{
        char str[256];
        fgets(str, 256, stdin);
        puts(str);

        return 0;
}
 
The only anoying thing about fgets is that you need to strip of the newline as it becomes part of the string.

The good news is code has already been provided in this thread to strip the last character of a string. It was inefficient due to two strlen calls, but that's an easy fix, and it would be easy to wrap in a function.

There is a C getline implementation, but it was added in FreeBSD after the most recent version adapted for OS X. Alternate implementations are available online if desired.

-Lee
 
The good news is code has already been provided in this thread to strip the last character of a string. It was inefficient due to two strlen calls, but that's an easy fix, and it would be easy to wrap in a function.

I agree, and in the case of using fgets on a file as requested in post #35 this is not a problem with, for example atof() that can convert the string regardless of nl.
 
Thanks.

It was inefficient due to two strlen calls, but that's an easy fix, and it would be easy to wrap in a function.
Could you show an efficient way.

Another problem: I use this method to get coordinates from an arbitrary position in a list of them from a text file:
Code:
- (void) getCoords: (int) i Array: (float **) a {
	char *line = (char *) malloc(50);
	for (int j = 0; j < i + 1; j++) {
	line = fgets(line, 50, fp);
	}
	char *x, *y, *z;
	x = (char*) malloc(20);
	y = (char*) malloc(20);
	z = (char*) malloc(20);
	
	x = strsep(&line, ";");
	y = strsep(&line, ";");
	z = strsep(&line, ";");
	
	float coords[] = {strtof(x, NULL), strtof(y, NULL), strtof(z, NULL)};
	*a = coords;
}
I print them as they come. However, only the first 32 coordinates are printed, then I get EXC_BAD_ACCESS at strtodg, which is in strtof's stack. What is the problem?
 
Code:
void chompChar (char *input) {
  int len = strlen(input);
  if(len > 0) input[len-1] = '\0';
}

This chomps the last character from any string. Adapting it to accept a character or list of characters to be chopped would be trivial.

As for that code... You are leaking all of the memory you malloc, so that's no good. a is float ** and coords is float[] (or float *). coords is on the stack, and you return a pointer to it, which is wrong. Is it the 32nd line that has the problem? So the 32nd call to this function? What are the arguments to atof when the crash occurs?

-Lee

Edit: oops, just saw *a. Still, returning a pointer to coords like that is a bad time.
 
Post the input data.

Post the stack trace from the crash.

Learn to use the debugger. When your program crashes, use the debugger to examine the data of the line that was read, the converted values, etc. to determine where the error is.

In all seriousness, if your only debugging strategy is to ask someone else to debug your code for you, then you really need to improve your skill set. This bug seems like a good one to learn the debugger on. You have a crash, it's consistent (same place), and it's isolated to a single method or function. It's almost perfect as a non-trivial but apparently isolated bug.

Oh, and all those mallocs in your method are leaking memory.
 
all those mallocs in your method are leaking memory.
What should I use instead of them?

Asking someone else to debug is not my only strategy. My strategies are using printf and looking at the call stack.
 
What should I use instead of them?

Asking someone else to debug is not my only strategy. My strategies are using printf and looking at the call stack.

x,y,z don't need to have memory allocated at all. Are you positive you understand pointers? You are assigning a pointer to some new memory to those variables, then immediately assign to them, losing the original pointer. You could never free the memory at that point. As for line, you need to call free on its pointer before you leave the method and lose the pointer.

The debugger must become part of your repertoire. printf can only take you so far, and you don't always have the luxury of endlessly editing production code.

-Lee
 
Doing free(&line) causes SIGABRT and this to be printed to the console: "ModelTest(6518,0x7fff7116ec20) malloc: *** error for object 0x7fff5fbff090: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug".
 
Doing free(&line) causes SIGABRT and this to be printed to the console: "ModelTest(6518,0x7fff7116ec20) malloc: *** error for object 0x7fff5fbff090: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug".

&line is the address where the char * line is stored, so it is char **. The storage for line is on the stack. The pointer it is storing was returned from malloc. This is what needs to be passed to free.

-Lee

Edit: by the way, did you ever compile and run my strsep example? tmp never has malloc run in that code. The print statements show you all the pointers involved, which might help in seeing what it's actually doing.
 
My strategies are using printf and looking at the call stack.

Then where is your debugging output?

Where is the crash call-stack (stack trace) I asked for?

Where is the data that causes the crash?

If those are your debugging strategy, then anyone else who you ask to debug your code will need to know those same things, especially the stack trace and the data that causes a crash.


Have you noticed that you perform no error checking at all in your code? You don't check for null from gets(), you don't check that strsep finds a ;, you don't check that the conversion works.
 
Call stack:
#0 0x7fff88c4fbeb in __strtodg
#1 0x7fff88c4fac3 in strtof_l
#2 0x10000209d in -[OpenGLView getCoords:Array:] at OpenGLView.m:177
#3 0x1000018bb in -[OpenGLView initWithFrame:] at OpenGLView.m:68
#4 0x7fff803aa198 in -[NSCustomView nibInstantiate]
#5 0x7fff80302263 in -[NSIBObjectData instantiateObject:]
#6 0x7fff8030164e in -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:]
#7 0x7fff802ffcd9 in loadNib
#8 0x7fff802ff1e9 in +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:eek:wnerBundle:]
#9 0x7fff802ff021 in +[NSBundle(NSNibLoading) loadNibNamed:eek:wner:]
#10 0x7fff802fc5a3 in NSApplicationMain
#11 0x100001399 in main at main.m:13

strtodg:
Code:
0x00007fff88c4fb4a  <+0000>  push   %rbp
0x00007fff88c4fb4b  <+0001>  mov    %rsp,%rbp
0x00007fff88c4fb4e  <+0004>  push   %r15
0x00007fff88c4fb50  <+0006>  push   %r14
0x00007fff88c4fb52  <+0008>  push   %r13
0x00007fff88c4fb54  <+0010>  push   %r12
0x00007fff88c4fb56  <+0012>  push   %rbx
0x00007fff88c4fb57  <+0013>  sub    $0x128,%rsp
0x00007fff88c4fb5e  <+0020>  mov    %rdi,%r12
0x00007fff88c4fb61  <+0023>  mov    %rsi,-0x100(%rbp)
0x00007fff88c4fb68  <+0030>  mov    %rdx,-0x108(%rbp)
0x00007fff88c4fb6f  <+0037>  mov    %rcx,-0x110(%rbp)
0x00007fff88c4fb76  <+0044>  mov    %r8,-0x118(%rbp)
0x00007fff88c4fb7d  <+0051>  mov    %r9,%rbx
0x00007fff88c4fb80  <+0054>  test   %r9,%r9
0x00007fff88c4fb83  <+0057>  jne    0x7fff88c4fb91 <__strtodg+71>
0x00007fff88c4fb85  <+0059>  mov    -0x17af9aec(%rip),%rax        # 0x7fff711560a0
0x00007fff88c4fb8c  <+0066>  mov    (%rax),%rbx
0x00007fff88c4fb8f  <+0069>  jmp    0x7fff88c4fba0 <__strtodg+86>
0x00007fff88c4fb91  <+0071>  cmp    $0xffffffffffffffff,%r9
0x00007fff88c4fb95  <+0075>  lea    -0x17af31dc(%rip),%rax        # 0x7fff7115c9c0 <__global_locale>
0x00007fff88c4fb9c  <+0082>  cmove  %rax,%rbx
0x00007fff88c4fba0  <+0086>  mov    %rbx,%rdi
0x00007fff88c4fba3  <+0089>  callq  0x7fff88d2a8c4 <dyld_stub_localeconv_l>
0x00007fff88c4fba8  <+0094>  mov    (%rax),%rax
0x00007fff88c4fbab  <+0097>  mov    %rax,-0x88(%rbp)
0x00007fff88c4fbb2  <+0104>  movl   $0x0,-0x3c(%rbp)
0x00007fff88c4fbb9  <+0111>  lea    -0x60(%rbp),%r13
0x00007fff88c4fbbd  <+0115>  movq   $0x0,-0x60(%rbp)
0x00007fff88c4fbc5  <+0123>  movq   $0x0,-0x68(%rbp)
0x00007fff88c4fbcd  <+0131>  mov    -0x108(%rbp),%rax
0x00007fff88c4fbd4  <+0138>  mov    (%rax),%eax
0x00007fff88c4fbd6  <+0140>  mov    %eax,-0xd4(%rbp)
0x00007fff88c4fbdc  <+0146>  mov    %r12,-0x50(%rbp)
0x00007fff88c4fbe0  <+0150>  lea    0x19(%rip),%rdx        # 0x7fff88c4fc00 <__strtodg+182>
0x00007fff88c4fbe7  <+0157>  mov    -0x50(%rbp),%rdi
0x00007fff88c4fbeb  <+0161>  cmpb   $0x2d,(%rdi)            //The problem is in this line.
0x00007fff88c4fbee  <+0164>  ja     0x7fff88c4fcf2 <__strtodg+424>
0x00007fff88c4fbf4  <+0170>  movzbl (%rdi),%eax
0x00007fff88c4fbf7  <+0173>  movslq (%rdx,%rax,4),%rax
0x00007fff88c4fbfb  <+0177>  add    %rdx,%rax
0x00007fff88c4fbfe  <+0180>  jmpq   *%rax
0x00007fff88c4fc00  <+0182>  faddl  (%rax)
0x00007fff88c4fc02  <+0184>  add    %al,(%rax)
0x00007fff88c4fc04  <+0186>  repnz add %al,(%rax)
0x00007fff88c4fc07  <+0189>  add    %dh,%dl
0x00007fff88c4fc09  <+0191>  add    %al,(%rax)
0x00007fff88c4fc0b  <+0193>  add    %dh,%dl
0x00007fff88c4fc0d  <+0195>  add    %al,(%rax)
0x00007fff88c4fc0f  <+0197>  add    %dh,%dl
0x00007fff88c4fc11  <+0199>  add    %al,(%rax)
0x00007fff88c4fc13  <+0201>  add    %dh,%dl
0x00007fff88c4fc15  <+0203>  add    %al,(%rax)
0x00007fff88c4fc17  <+0205>  add    %dh,%dl
0x00007fff88c4fc19  <+0207>  add    %al,(%rax)
0x00007fff88c4fc1b  <+0209>  add    %dh,%dl
0x00007fff88c4fc1d  <+0211>  add    %al,(%rax)
0x00007fff88c4fc1f  <+0213>  add    %dh,%dl
0x00007fff88c4fc21  <+0215>  add    %al,(%rax)
0x00007fff88c4fc23  <+0217>  add    %ah,%ch
0x00007fff88c4fc25  <+0219>  add    %al,(%rax)
0x00007fff88c4fc27  <+0221>  add    %ah,%ch
0x00007fff88c4fc29  <+0223>  add    %al,(%rax)
0x00007fff88c4fc2b  <+0225>  add    %ah,%ch
0x00007fff88c4fc2d  <+0227>  add    %al,(%rax)
0x00007fff88c4fc2f  <+0229>  add    %ah,%ch
0x00007fff88c4fc31  <+0231>  add    %al,(%rax)
0x00007fff88c4fc33  <+0233>  add    %ah,%ch
0x00007fff88c4fc35  <+0235>  add    %al,(%rax)
0x00007fff88c4fc37  <+0237>  add    %dh,%dl
0x00007fff88c4fc39  <+0239>  add    %al,(%rax)
0x00007fff88c4fc3b  <+0241>  add    %dh,%dl
0x00007fff88c4fc3d  <+0243>  add    %al,(%rax)
0x00007fff88c4fc3f  <+0245>  add    %dh,%dl
0x00007fff88c4fc41  <+0247>  add    %al,(%rax)
0x00007fff88c4fc43  <+0249>  add    %dh,%dl
0x00007fff88c4fc45  <+0251>  add    %al,(%rax)
0x00007fff88c4fc47  <+0253>  add    %dh,%dl
0x00007fff88c4fc49  <+0255>  add    %al,(%rax)
0x00007fff88c4fc4b  <+0257>  add    %dh,%dl
0x00007fff88c4fc4d  <+0259>  add    %al,(%rax)
0x00007fff88c4fc4f  <+0261>  add    %dh,%dl
0x00007fff88c4fc51  <+0263>  add    %al,(%rax)
0x00007fff88c4fc53  <+0265>  add    %dh,%dl
0x00007fff88c4fc55  <+0267>  add    %al,(%rax)
0x00007fff88c4fc57  <+0269>  add    %dh,%dl
0x00007fff88c4fc59  <+0271>  add    %al,(%rax)
0x00007fff88c4fc5b  <+0273>  add    %dh,%dl
0x00007fff88c4fc5d  <+0275>  add    %al,(%rax)
0x00007fff88c4fc5f  <+0277>  add    %dh,%dl
0x00007fff88c4fc61  <+0279>  add    %al,(%rax)
0x00007fff88c4fc63  <+0281>  add    %dh,%dl
0x00007fff88c4fc65  <+0283>  add    %al,(%rax)
0x00007fff88c4fc67  <+0285>  add    %dh,%dl
0x00007fff88c4fc69  <+0287>  add    %al,(%rax)
0x00007fff88c4fc6b  <+0289>  add    %dh,%dl
0x00007fff88c4fc6d  <+0291>  add    %al,(%rax)
0x00007fff88c4fc6f  <+0293>  add    %dh,%dl
0x00007fff88c4fc71  <+0295>  add    %al,(%rax)
0x00007fff88c4fc73  <+0297>  add    %dh,%dl
0x00007fff88c4fc75  <+0299>  add    %al,(%rax)
0x00007fff88c4fc77  <+0301>  add    %dh,%dl
0x00007fff88c4fc79  <+0303>  add    %al,(%rax)
0x00007fff88c4fc7b  <+0305>  add    %dh,%dl
0x00007fff88c4fc7d  <+0307>  add    %al,(%rax)
0x00007fff88c4fc7f  <+0309>  add    %ah,%ch
0x00007fff88c4fc81  <+0311>  add    %al,(%rax)
0x00007fff88c4fc83  <+0313>  add    %dh,%dl
0x00007fff88c4fc85  <+0315>  add    %al,(%rax)
0x00007fff88c4fc87  <+0317>  add    %dh,%dl
0x00007fff88c4fc89  <+0319>  add    %al,(%rax)
0x00007fff88c4fc8b  <+0321>  add    %dh,%dl
0x00007fff88c4fc8d  <+0323>  add    %al,(%rax)
0x00007fff88c4fc8f  <+0325>  add    %dh,%dl
0x00007fff88c4fc91  <+0327>  add    %al,(%rax)
0x00007fff88c4fc93  <+0329>  add    %dh,%dl
0x00007fff88c4fc95  <+0331>  add    %al,(%rax)
0x00007fff88c4fc97  <+0333>  add    %dh,%dl
0x00007fff88c4fc99  <+0335>  add    %al,(%rax)
0x00007fff88c4fc9b  <+0337>  add    %dh,%dl
0x00007fff88c4fc9d  <+0339>  add    %al,(%rax)
0x00007fff88c4fc9f  <+0341>  add    %dh,%dl
0x00007fff88c4fca1  <+0343>  add    %al,(%rax)
0x00007fff88c4fca3  <+0345>  add    %dh,%dl
0x00007fff88c4fca5  <+0347>  add    %al,(%rax)
0x00007fff88c4fca7  <+0349>  add    %dh,%dl
0x00007fff88c4fca9  <+0351>  add    %al,(%rax)
0x00007fff88c4fcab  <+0353>  add    %al,%ah
 
What about the input file? Have you NSLog'd line,x,y,z? Declare a char ** that you assign &line to so strsep can change it. I'll keep asking if you read,compiled, and ran my example from post #29.

-Lee
 
The code in post 29 is not relevant as this problem occurs in strtof's call stack, not strsep's. I print every coordinate. They are printed up to line 32 in the input file, then EXC_BAD_ACCESS stops it. There is nothing special in line 33.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.