LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-30-2010, 02:42 PM   #1
Repgahroll
LQ Newbie
 
Registered: Aug 2009
Posts: 10

Rep: Reputation: 0
C++ - "snprintf" inside "for" doesn't work as expected. (int to char*)


I need to convert an int array into a char* array.
I'm using the following code:
Code:
    for (int x = 0; x < 8; x++) {
        snprintf(buffer,32,"%d\0", x);
        y[x]=buffer;
    }

    for (int x = 0; x < 8; x++) {
        cout<<y[x]<<endl;
    }
but it returns me
Code:
7
7
7
7
7
7
7
7
and I can't fix it.
Can someone help me please?
Thanks in advance.

Last edited by Repgahroll; 08-30-2010 at 02:58 PM.
 
Old 08-30-2010, 03:12 PM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Repgahroll View Post
I need to convert an int array into a char* array.
I'm using the following code:
Code:
    for (int x = 0; x < 8; x++) {
        snprintf(buffer,32,"%d\0", x);
        y[x]=buffer;
    }

    for (int x = 0; x < 8; x++) {
        cout<<y[x]<<endl;
    }
but it returns me
Code:
7
7
7
7
7
7
7
7
and I can't fix it.
Can someone help me please?
Thanks in advance.
What did you mean to do by the item in red ? How about seeing the whole code ? Did you use '-Wall -Wextra -Wformat=2 -O2' during compilation ? If yes, were there any warnings ?
 
Old 08-30-2010, 03:31 PM   #3
jf.argentino
Member
 
Registered: Apr 2008
Location: Toulon (France)
Distribution: FEDORA CORE
Posts: 493

Rep: Reputation: 50
snprintf change the content of "buffer": it fill each case with the string representation of "x" (i'm assuming buffer is defined as "char buffer[32]" or equivalent).
so each round of your "for" loop, "buffer" is over written _AND_ "y[x]=buffer;" just copy the address of the "buffer" array (the position of its 1st char in memory), i'm assuming here that "y" is defined as "char* y[8]" or similar. This address doesn't change, its content does.
Then the 2nd "for" loop just display the content of the x'th address "y[x]" (="buffer" content).

REMARK: if your coding in C++, use C++ string object and methods. If you're sing pure C, use "printf" not "cout". MixingC and C++ is a bad habbit.
 
Old 08-30-2010, 03:32 PM   #4
JohnGraham
Member
 
Registered: Oct 2009
Posts: 467

Rep: Reputation: 139Reputation: 139
Quote:
Originally Posted by Repgahroll View Post
I'm using the following code:
Code:
    for (int x = 0; x < 8; x++) {
        snprintf(buffer,32,"%d\0", x);
        y[x]=buffer;
    }

    for (int x = 0; x < 8; x++) {
        cout<<y[x]<<endl;
    }
I think there are some fundamental flaws in the way you're using arrays. For example, "snprintf(buffer,32,"%d\0", x);" is always printing to the first element of buffer (you probably want "buffer[x]") and similarly "y[x]=buffer;" is always reading from the first element of the buffer (again, you probably want "buffer[x]") giving the (correct) printed result.

By making these two changes, your code will probably work, but if you don't understand why then you really need to read-up on arrays and pointers.
 
Old 08-30-2010, 03:32 PM   #5
Repgahroll
LQ Newbie
 
Registered: Aug 2009
Posts: 10

Original Poster
Rep: Reputation: 0
Quote:
What did you mean to do by the item in red ? How about seeing the whole code ? Did you use '-Wall -Wextra -Wformat=2 -O2' during compilation ? If yes, were there any warnings ?
It is meant to copy the buffer value into different items of the y array (of chars).
Code:
#include <ncurses.h>
#include <menu.h>
#include <iostream>

using namespace std;

char buffer [16];
char *y[32];

int main() {

    for (int x = 0; x < 8; x++) {
        snprintf(buffer,32,"%d\0", x);
        y[x]=buffer;
    }

    for (int x = 0; x < 8; x++) {
        cout<<y[x]<<endl;
    }
}
Command: g++ -o bin main.cpp -Wall -Wextra -Wformat=2 -O2
Output:
Code:
main.cpp: In function ‘int main()’:
main.cpp:13: warning: embedded ‘\0’ in format
main.cpp:13: warning: embedded ‘\0’ in format
In file included from /usr/include/stdio.h:910,
                 from /usr/include/ncurses.h:141,
                 from main.cpp:1:
In function ‘int snprintf(char*, size_t, const char*, ...)’,
    inlined from ‘int main()’ at main.cpp:13:
/usr/include/bits/stdio2.h:66: warning: call to int __builtin___snprintf_chk(char*, unsigned int, int, unsigned int, const char*, ...) will always overflow destination buffer
Thank you.
 
Old 08-30-2010, 03:37 PM   #6
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Repgahroll View Post
It is meant to copy the buffer value ...
How do you define the "buffer value" ? I.e. you describe 'buffer' as

Code:
char buffer [16];
- in "C" this means an array of 16 elements, each element type is 'char'. So, how do you define the "buffer value" in terms of the array and its elements ?
 
Old 08-30-2010, 03:43 PM   #7
jf.argentino
Member
 
Registered: Apr 2008
Location: Toulon (France)
Distribution: FEDORA CORE
Posts: 493

Rep: Reputation: 50
Quote:
It is meant to copy the buffer value into different items of the y array (of chars).
So what is the "buffer" purpose?
Did you understand my 1st post?
 
Old 08-30-2010, 03:49 PM   #8
Repgahroll
LQ Newbie
 
Registered: Aug 2009
Posts: 10

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by jf.argentino View Post
snprintf change the content of "buffer": it fill each case with the string representation of "x" (i'm assuming buffer is defined as "char buffer[32]" or equivalent).
so each round of your "for" loop, "buffer" is over written _AND_ "y[x]=buffer;" just copy the address of the "buffer" array (the position of its 1st char in memory), i'm assuming here that "y" is defined as "char* y[8]" or similar. This address doesn't change, its content does.
Then the 2nd "for" loop just display the content of the x'th address "y[x]" (="buffer" content).

REMARK: if your coding in C++, use C++ string object and methods. If you're sing pure C, use "printf" not "cout". MixingC and C++ is a bad habbit.
So... why the last -not the first- value of x is displayed for the first y that was set when x was 0?
Quote:
Originally Posted by JohnGraham View Post
I think there are some fundamental flaws in the way you're using arrays. For example, "snprintf(buffer,32,"%d\0", x);" is always printing to the first element of buffer (you probably want "buffer[x]") and similarly "y[x]=buffer;" is always reading from the first element of the buffer (again, you probably want "buffer[x]") giving the (correct) printed result.

By making these two changes, your code will probably work, but if you don't understand why then you really need to read-up on arrays and pointers.
I understand, however, if the buffer isn't set as array, i get segfault, even if i use something like "sprintf(y[x], "%d", x);" i get segfaults.

I just want to convert an array of integers into an array of chars so i can use it on ncurses menus (i'm learning ncurses).I though it was going to be a very simple thing.

Thanks.

Last edited by Repgahroll; 08-30-2010 at 03:54 PM.
 
Old 08-30-2010, 03:58 PM   #9
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Repgahroll View Post
So... why the last -not the first- value of x is displayed for the first y that was set when x was 0?
...
'buffer' is all the time the same, and as such it holds the data it got after the last modification.

I suggest to answer my question in http://www.linuxquestions.org/questi...1/#post4082765 - it will help you to understand what you understand/do wrong.
 
Old 08-30-2010, 04:00 PM   #10
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Repgahroll View Post
...
Command: g++ -o bin main.cpp -Wall -Wextra -Wformat=2 -O2
Output:
Code:
main.cpp: In function ‘int main()’:
main.cpp:13: warning: embedded ‘\0’ in format
main.cpp:13: warning: embedded ‘\0’ in format
In file included from /usr/include/stdio.h:910,
                 from /usr/include/ncurses.h:141,
                 from main.cpp:1:
In function ‘int snprintf(char*, size_t, const char*, ...)’,
    inlined from ‘int main()’ at main.cpp:13:
/usr/include/bits/stdio2.h:66: warning: call to int __builtin___snprintf_chk(char*, unsigned int, int, unsigned int, const char*, ...) will always overflow destination buffer
Thank you.
You need to make your code such it produces no warnings. The item in red is really grave.
 
Old 08-30-2010, 04:05 PM   #11
Repgahroll
LQ Newbie
 
Registered: Aug 2009
Posts: 10

Original Poster
Rep: Reputation: 0
Okay, but even a simple code like this:
Code:
#include <iostream>
#include <stdio.h>

using namespace std;

char *y;
int x = 32;

int main() {
        sprintf(y, "%d", x);
        cout<<y<<endl;
}
is returning segfault. what's wrong with it?
 
Old 08-30-2010, 04:07 PM   #12
jf.argentino
Member
 
Registered: Apr 2008
Location: Toulon (France)
Distribution: FEDORA CORE
Posts: 493

Rep: Reputation: 50
"char *y;"
You didn't allocate any space for a char array, you're allocating space for an address pointing to a (or many) char(s)
 
Old 08-30-2010, 04:21 PM   #13
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
C beginners usually get confused by the lack of support in C for strings.

In C, you typically use arrays of characters instead of strings. But an array of characters is nowhere near as easy to use as a string. You need to understand all the basic concepts of arrays and pointers in C.

This is one thing that makes C++ a better beginner language. Beginners tend to write things that need strings before they learn enough to understand pointers and arrays. C++ has a string class.

Quote:
Originally Posted by Repgahroll View Post
It is meant to copy the buffer value into different items of the y array (of chars).
Code:
char buffer [16];
char *y[32];
Because buffer is an array, its name does not refer to its contents (the array of characters). Its name refers to the address of the first character.

The y you declared is not an array of characters. It is an array of character pointers.

Code:
        y[x]=buffer;
So that doesn't copy the contents of the buffer. It copies the address of the buffer.

Since you said "C++" not "C". Maybe you don't need to learn so much about using character arrays instead of strings. Maybe you can mostly use strings.

snprintf would still need a character array for its destination. I'm not sure whether it is worth looking for a more C++ appropriate substitute for snprintf.

You mentioned your target is ncurses, which is based on a C interface. I don't know whether its C++ bindings make it support C++ well (strings etc.) or whether you still need char arrays there.

But even if you need char arrays at the start and end of the life of each string, you still might be less confused if you use strings in between.

Instead of
char *y[32];
try
std::string y[32];
(You'll need #include <string> at the top of your file)
Then when you do
y[x]=buffer;
it would really mean copy the contents of the buffer as you intend, rather than store the address.

Last edited by johnsfine; 08-30-2010 at 04:34 PM.
 
Old 08-30-2010, 04:41 PM   #14
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Repgahroll View Post
Okay, but even a simple code like this:
Code:
#include <iostream>
#include <stdio.h>

using namespace std;

char *y;
int x = 32;

int main() {
        sprintf(y, "%d", x);
        cout<<y<<endl;
}
is returning segfault. what's wrong with it?
The word "pointer" in programming originates from the verb "to point to".

The wrong thing with the program is that you haven't asked yourself the question: "Where does the 'char *y' pointer point to ?".

Had you used 'Wall -Wextra -Wformat=2 -O2' during compilation, you would have seen warnings about 'y' being uninitialized. 'y' has a random/garbage value and thus points to a random memory location, and that causes segmentation fault.

I suggest to pick any C/C++ tutorial and learn about pointers first.
 
Old 08-31-2010, 08:27 AM   #15
Repgahroll
LQ Newbie
 
Registered: Aug 2009
Posts: 10

Original Poster
Rep: Reputation: 0
Okay guys. Learning pointers was the key.
Thank you very much!
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
evdev/xorg help? USB mouse/kbd: 2.6.24="just works">2.6.25="unplug/replug to work". GrapefruiTgirl Linux - Hardware 4 12-13-2012 02:23 PM
Symlinks working from "inside" 'chroot' to "outside" ? amn Linux - Newbie 2 12-07-2007 01:09 AM
Standard commands give "-bash: open: command not found" even in "su -" and "su root" mibo12 Linux - General 4 11-11-2007 10:18 PM
LXer: Displaying "MyComputer", "Trash", "Network Servers" Icons On A GNOME Desktop LXer Syndicated Linux News 0 04-02-2007 08:31 AM
Any way to get "Alice"; "Call of Duty" series and "Descent 3" to work? JBailey742 Linux - Games 13 06-23-2006 01:34 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:12 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration