LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   How do I point a char pointer to a part of another char array? (https://www.linuxquestions.org/questions/programming-9/how-do-i-point-a-char-pointer-to-a-part-of-another-char-array-842462/)

trist007 11-04-2010 09:44 PM

How do I point a char pointer to a part of another char array?
 
Programming in C.
I have two char arrays.

char buf1[1024];
char buf2[1024];

Aren't buf1 and buf2 also pointers?

I read in 1024 bytes into buf1 which contain about 300 bytes of characters with newlines. The data is basically a few English sentences. I'm trying to scan buf1 for newlines and then stop at the 1st newline and copy the rest of the data from that 1st newline into buf2.

So I run a for loop to look for that new line.
Code:

for(i=0; i<1024;i++)  {
    if((strcmp(&buf1[i], "\n")) == 0)  {
          buf2 = buf1[i+1];      // trying to set buf2 to point to the data after the first newline in buf1
          }
    }

In the for loop do I have to use &buf1[i] or will buf[i] work as well?

However I'm getting the error 'incompatible types of assignment' for the line
buf2 = buf1[i];

Could somebody explain this process better. On the above statement buf2 is a pointer and buf1[i] is a string? a char?

Please be as detailed as possible. I really want to understand this.

Dark_Helmet 11-04-2010 10:57 PM

Ok, I think you're getting some things jumbled.

You declare buf1 and buf2 as:
Code:

char buf1[1024];
char buf2[1024];

Therefore, you are declaring buf1 and buf2 as character arrays.

You need to distinguish the underlying data types from what the data type represents. I say that because I think you're getting confused by thinking that character arrays, character pointers, and strings are all synonymous--they aren't.

A string is an interpretation of underlying data. The compiler looks at a starting memory address, and "displays" each byte as a character until it reaches a byte with a value of 0 (the end-of-string marker).

A character pointer is a variable that stores a memory address, and indicates that the memory it's addressing contains characters. But the pointer's value (the address itself) can be modified.

A character array is a variable fixed at one memory address, with enough space available to store a fixed number of characters. For lack of a better analogy, think of it as a constant character pointer--the address cannot be modified.

Now, you can use both a character pointer and a character array whenever you need to supply a string to your code. And I think that might be part of what's tripping you up. A character array, with no subscript, is a pointer to the first element in the array. When you apply a subscript to an array, you're left with the character value located at that index in the array.

With that out of the way...

Your statement:
Code:

buf2 = buf1[i+1];
is illegal for two reasons. First, as the compiler tells you, they are incompatible types. buf2 is a character array. buf1[i+1] is a character. Therefore, you are trying to assign a character to a character array.

Second, buf2 is a character array, and its location in memory cannot be modified. Therefore, any assignments to buf2 (without an appropriate subscript) will also result in an error.

I assume what you want is for buf2 to contain the same characters as buf1, from a given starting position. You should use the strcpy() or strncpy() functions for that purpose. You will need to use the address-of operator (&) that you touched on in your post to make this work correctly. For example:
Code:

strcpy( buf2, &buf1[i+1] )
If you want the "simplicity" of your original statement to work (buf2 = &buf[i+1]), then you will need to use a character pointer for buf2. Though, doing so might cause lots of grief if you are not familiar with all the pitfalls of working with pointers.

kbp 11-04-2010 11:02 PM

I seem to keep pointing people to this, but it really is easy to follow:

http://www.highercomputingforeveryone.com/

Carl takes you through the basics in very small steps,

Regarding your immediate problem, you really shouldn't copy a buffer one character at a time, this will perform badly in terms of compute cycles. Try to come up with a solution that performs a string copy for example, or maybe you could just not allocate buff2 - create and initialise it pointing at [buff1+i]

hth

paulsm4 11-05-2010 01:13 AM

Quote:

do I have to use &buf1[i] or will buf[i] work as well?
&buf1[i] is a pointer. It points to a character. This is correct:
Code:

if((strcmp(&buf1[i], "\n"))..
buf1[i] is a character. This is NOT correct:
Code:

if((strcmp(buf1[i], "\n"))..
<= In fact, it's an almost guaranteed access violation ;)

'Hope that helps

trist007 11-05-2010 09:46 AM

I don't understand why when you use strcmp()
why wouldn't you use buf1[i] which is a char to compare it with "\n" which is another char?
Why is &buf1[i] which is a memory address where the char in the ith index is stored correct when comparing to another char "\n"?

Dark_Helmet 11-05-2010 11:15 AM

Quote:

Originally Posted by trist007
I don't understand why when you use strcmp()
why wouldn't you use buf1[i] which is a char to compare it with "\n" which is another char?
Why is &buf1[i] which is a memory address where the char in the ith index is stored correct when comparing to another char "\n"?

Because chars and strings are not the same thing.

First, strcmp() compares strings. By comparing strings, the process necessarily compares individual characters, but strcmp() will continue to compare characters including and until a NULL is encountered.

So, for your first question:
Quote:

why wouldn't you use buf1[i] which is a char to compare it with "\n" which is another char?
1. buf1[i] is a char, correct. That, however, is the problem. strcmp() compares strings. As such, it needs the address of the first character to start comparing--not the value of the first character itself.

2. "\n" is NOT a character. It is a literal string. It is represented in memory as two sequential characters at the following indexes: [0]: \n [1]: NULL. Use of "\n" in code is replaced with the address in memory where the literal string is stored. Please note: "\n" is a literal string -- '\n' is a literal character. The quoting makes a difference.

If you want to compare two characters individually, you would do it like so:
Code:

if( buf1[i] == '\n' )
{
  printf( "Newline found\n" );
}
else
{
  printf( "Not a newline\n" );
}

Quote:

Why is &buf1[i] which is a memory address where the char in the ith index is stored correct when comparing to another char "\n"?
It is syntactically correct. That is, it meets the requirements of strcmp()--two strings as arguments. Whether it is logically correct for your program is another matter.

But your hangup I believe, is again thinking that "\n" is a character. As mentioned above, it is actually a literal string. It represents a sequence of two characters--not one.

paulsm4 11-05-2010 12:08 PM

Hi, again:
Quote:

Q: I don't understand why when you use strcmp(). Why wouldn't you use buf1[i] which is a char to compare it with "\n" which is another char?

Why is &buf1[i] which is a memory address where the char in the ith index is stored correct when comparing to another char "\n"?
Code:

  // Compare string "\n" with string "\n":
  char *s = "\n";
  if (strcmp (s, "\n") == 0) ...

  // Since the string is only one byte (plus the null byte delimiter),
  // then it's equivalent to this:
  if (s[0] == '\n') ...

But that has nothing to do with what I thought was your original question: "can I use strcmp (buf[i]) instead of strcmp (&buf[i])"? No - you can't ;)

PS:
Q: does this make sense?
Quote:

Q: Do I have to use &buf1[i] or will buf[i] work as well?

A: &buf1[i] is a pointer. It points to a character. This is correct:
Code:

if((strcmp(&buf1[i], "\n"))..
buf1[i] is a character. This is NOT correct:
Code:

if((strcmp(buf1[i], "\n"))..


johnsfine 11-05-2010 12:43 PM

Quote:

Originally Posted by trist007 (Post 4149740)
char buf1[1024];
char buf2[1024];

Aren't buf1 and buf2 also pointers?

Consider this code:
Code:

int count = 5;
...
23 = count; /* error */

count and 23 both can be used as integers. But obviously you can't use 23 as the left side of an assignment.

Similarly,
Code:

char *pnt;
char buf2[1024];

pnt and buf2 both can be used as char pointers, but using buf2 as the left side of an assignment is wrong in the same way using 23 as the left side of an assignment was wrong.

Quote:

Code:

strcmp(&buf1[i], "\n")
...do I have to use &buf1[i] or will buf[i] work as well?
Neither!

buf1[i] is a character, not an address, so passing it as an address to strcmp would seg fault (as many people already explained).
&buf1[i] is the address of a substring that might start with '\n' (which is what you said you want to test) but strcmp would test whether it both starts and ends with '\n', which is not what you want.

So instead of strcmp(&buf1[i], "\n")==0 what you want is buf1[i]=='\n'

Quote:

Originally Posted by trist007 (Post 4150212)
Why is &buf1[i] which is a memory address where the char in the ith index is stored correct when comparing to another char "\n"?

"\n" is not a char.
"\n" is the address where that char followed by a null is stored.
'\n' is the char.

strcmp compares two sequences of characters, and you must pass it their addresses. To compare individual characters, you just use == as I suggested above.

For the other error...
Quote:

buf2 = buf1[i+1];
Earlier posts have told you the many things wrong with that line of code. But I don't know whether you described what you hoped it would do well enough to get corrected code.

Quote:

stop at the 1st newline and copy the rest of the data
I think that would be
Code:

if ( buf1[i] == '\n' ) {
  strcpy(buf2, buf1+i+1);
  break; }

but it is hard to be sure that is what is intended by your description. It is quite far from what you coded.

trist007 11-06-2010 07:56 PM

Thanks a ton guys, that really cleared it up.


All times are GMT -5. The time now is 05:45 PM.