Hi there. I was trying out a relatively simple program to convert a line of text into a 2-D string array which each word in a different row but it isn't working.

The program is

#include <iostream>
void main()
{
    int i, j, k=0;
    char line[30]={"This is a test"}, temp[5][5];
    for(i=0; line[k]!=NULL; i++)
        for(j=0; line[k]!=" "; j++)
            temp[i][j]=line[k++];
    for(i=0; i<5; i++)
        cout<<line[i];
}

This is the error that comes up:

\Desktop\test.cpp(7) : error C2446: '!=' : no conversion from 'char *' to 'int'
This conversion requires a reinterpret_cast, a C-style cast or function-style cast

\Desktop\test.cpp(7) : error C2040: '!=' : 'int' differs in levels of indirection from 'char [2]'

This is the line in which the error lies

for(j=0; line[k]!=" "; k++)

The error goes away if I add an asterisk before the " " like so:

for(j=0; line[k]!=*" "; k++)

The program runs but doesn't end which I'm assuming is because of an infinite loop.

I'm a C++ beginner and any help would be much appreciated.

Recommended Answers

All 32 Replies

try

1.
      for(j=0; line[k]!=' '; k++)

just a guess

try

1.
      for(j=0; line[k]!=' '; k++)

just a guess

No that doesn't work. Again it seems to have gone in an infinite loop.

NULL is not the right thing to be testing for, you want to test for '\0' instead.

seanbp is right, you want a space character, which is ' ' (single quotes)

However, in one of the cases you need to check to make sure the character is not equal to a space and is not equal to '\0'

Keep a separate "word" counter for each time you encounter a space, use that as your first index of your temp array.

Also, make sure that you append a null terminus ('\0') at the end of each word, otherwise you're going to get garbage when you cout the values -- you accounted for it in your array size but didn't do it in your code.

jonsca, in C++ you don't need the implicit character conversion involved with '\0', you just need 0.

@OP By the way, main always returns an int according to the standard

@seanbp

I believe you are correct, but when matching character for character, you probably need to use '\0'. I'll have to defer to a third party to referee. :)

Bear with me, I'm trying to come up with an example and not succeeding.

Okay, LOL show me an example of what you mean (not to take this OT, but it might be helpful to the OP also).

I think you're right. You'd want to compare a char with a char. Now I'm thinking 0 is an int by default so you'd need a cast. Example, in:

'\0' == 0

is there an implicit cast? Probably.
For the original poster, you're reading a two dimensional array as one and fetching uninitialized data, start by removing the {} around your string (see at your k counter).

I'm sorry, can you please explain a bit more clearly what exactly it is that I'm doing wrong?

0 and '\0' are identical and can be used interchangealy, which one you use is only a matter of programming style.

commented: Thanks. +6

I thought that NULL also represents a null character. If it doesn't then what is it used for?

NULL is used for pointers -- many compilers define NULL as (void *)0, which is not the same as 0.

(ignore this post or delete it)

No, it's no problem. The easiest way to show yourself what's going on is to print out the values of i,j,k at each step.

The issues are: once you get to the last word, you are looking for another space and there isn't one. Have your program look for != '\0' && !=' '. Also, you need to put a null after each string, so at temp[j+1] put '\0'. The last thing is, you need to increment k once more after you find a word so you can skip over the space.

Ancient Dragon is correct, NULL is not the same as a null terminator.

0 and '\0' are identical and can be used interchangealy, which one you use is only a matter of programming style.

Thanks AD, it took me a couple of little programs to convince myself. :) I'm not sure why that never sunk in.

The issues are: once you get to the last word, you are looking for another space and there isn't one. Have your program look for != '\0' && !=' '.

The last thing is, you need to increment k once more after you find a word so you can skip over the space.

Ah okay. I will edit these. Thanks

Also, you need to put a null after each string, so at temp[j+1] put '\0'.

I didn't really get this though. Why is there a need to put a null after a string row? Isn't it null by default?

He meant that each string needs to have a null byte -- that's just the way C strings work. All the functions in string.h expect strings to be null terminated. If they are not, then they are just character arrays, not considered strings. So in your declaration of temp you have to make room for the charcters you want to put in the strings plus one more for the null terminating character.

Try printing out what's in temp to start with, there will be junk there, so you can't assume there will be a null in the space after your string. Edit: ^^^^ also what AD said.

Alright, here's the updated code:

#include <iostream>
int main()
{
    int, i, j, k=0;
    char line[30]={"This is a test"}, temp[5][5];
    for(i=0; line[k]!='\0'; temp[i][j]='\0', i++, k++)
        for(j=0; line[k]!=' ' && line[k]!='\0'; j++)
            temp[i][j]=line[k];
    for(i=0; i<5; i++)
        cout<<temp[i]; 
}

When I run it, a windows error message pops up: "test2.exe has encountered a problem and needs to close". Boy do I suck at this :s

EDIT: It can't even print the values of all the variables so I can know what's wrong. It just spazzes.

for(i=0; line[k]!='\0'[B]; temp[i][j]='\0'[/B], i++, k++)

I wouldn't worry about the part in bold, I was just saying that you should be aware that temp is filled with garbage when you declare it.

Do one more k increment after you've found a word (so after your j loop is complete) so you can skip the space. In conjunction with that, put a '\0' after your last character (since j increments one more time before the for loop test fails, put it at temp[j], but after the j loop)

Boy do I suck at this

You don't, so don't worry about it. Once you learn std::strings you can put these aside unless you need them. C-strings are important to understand, but there are library functions (in <cstring> that make things easier).

If you declare temp like below then you won't have to worry about null terminating the strings because the compiler will flood all the bytes of temp with 0. char temp[5][5] = {0};

If I declare temp[5][5]=0 in the beginning and then initialise with strings later on, which there still be junk in the variable or will the characters not being occupied by the string continue to be null?

for(i=0; line[k]!='\0'[B]; temp[i][j]='\0'[/B], i++, k++)

I wouldn't worry about the part in bold

In conjunction with that, put a '\0' after your last character (since j increments one more time before the for loop test fails, put it at temp[j], but after the j loop)

Also I'm sorry but I don't quite get this. First you say I needn't worry about the part in bold then you say I need to but a '\0' after my last character by equating temp[j] to it after the j loop, but isn't that what the bolded part is doing?

If I declare temp[5][5]=0 in the beginning and then initialise with strings later on, which there still be junk in the variable or will the characters not being occupied by the string continue to be null?

The characters that are not changed will still contain 0.

Also I'm sorry but I don't quite get this. First you say I needn't worry about the part in bold then you say I need to but a '\0' after my last character by equating temp[j] to it after the j loop, but isn't that what the bolded part is doing?

Sure, sorry it's confusing. I'm saying you don't need to take the time to write in '\0' everywhere just to write over it again.

Most if not all functions dealing with cstrings will read only to the null terminus ('\0')
So if you have an array:

|   |   |   |   |   |  array boundaries

| $ | / | È | º | $ |  declare it, there's junk in each space     
| i | s | È | º | $ |  write in 'i' + 's', if you try to output you'll get "is" + garbage
| i | s | 0 | º | $ |  added the null terminus

Now if you check the length, the function will report 2 characters
If you do a strcpy, it will copy "is"+'\0' and nothing else

So, you can take the time to write in a null everywhere, but it's probably not necessary.

Others may have a different opinion...

Alright, so if it isn't necessary then why isn't the program working? I'm incrementing k twice after a word like you said (k+=2) but the program still keeps crashing.

I also initialised all the characters of temp to null

char temp[i][j]={0};

but the program still keeps crashing :(

I had said to only increment it once after each word.

Put in a statement that looks like this:

std::cout<<"temp["<<i<<"]["<<j<<"] = "<<line[k]<<std::endl;
right after you've written it into the array (but before you've incremented k again)

This should show you where your storage of the chars is off. Part of the difficulty here is that you are using a loop variable that's not local to the loop. Once control goes back to the top of the for loop, j will increment one more time, then the condition will be tested.

I had said to only increment it once after each word.

Actually you posted this:

Do one more k increment after you've found a word (so after your j loop is complete) so you can skip the space.

You told me to increment it once more when I was already incrementing it once after the j loop.

Put in a statement that looks like this:

std::cout<<"temp["<<i<<"]["<<j<<"] = "<<line[k]<<std::endl;
right after you've written it into the array (but before you've incremented k again)

This should show you where your storage of the chars is off. Part of the difficulty here is that you are using a loop variable that's not local to the loop. Once control goes back to the top of the for loop, j will increment one more time, then the condition will be tested.

Hmm alright, do I put that bit of code within the for loop or in the place where I'm incrementing k but just before it. Also, what does this bit of code do exactly? I haven't come across something like std::cout while I'm learning C++.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.