itoa creates an infinite loop in C++ - c++

This is very strange. itoa(); seems to create an infinite loop.
for(int i = 0; i < 10; i++)
{
char buffer[1];
itoa(i, buffer, 10);
std::cout << buffer;
}
Why on earth does it do that? I've tried using different variables than i, numerical values without variables (i.e. itoa(1, buffer, 10);), it still keeps ending up in an infinite loop.
I've tried to google without much success, I found an old mail about it here.
I am using Windows XP 32 bit and Code::Blocks (with GCC) as a compiler.
Does anyone know what's wrong? Thanks in advance.

itoa null-terminates the string it produces, but you haven't made buffer large enough to hold the terminating NUL character. Try:
for (int i = 0; i < 10; i++)
{
char buffer[2];
itoa(i, buffer, 10);
std::cout << buffer;
}

Why on earth are you using a general number conversion routine for single digits?
for (int i = 0; i < 10; i++)
std::cout << char('0' + i);
(You need the cast back to char so that the compiler uses the correct overload of <<. The C++ standard guarantees that the character constants '0' through '9' have consecutive numeric values.)

Your buffer is too small -- itoa will write a null-terminated string, so your buffer will need at a minimum 2 bytes to hold values from 0-9.

Related

Is there a simpler way to define a condition in a for loop in C++?

Consider an array arr[10] of size 10. While getting/displaying data, we use a for loop of the following common syntax
for(int i=0;i<10;i++)
In case of a string, it is like
for(int i=0;strlen(arr)>i;i++)
But I've read somewhere that a simpler expression like arr[i] could just be used in the place of condition. I've tried running a code with that condition. But I get an error. So is there a similar, simple condition expression that can be used with arrays/string?
Since you said simple and c++, use std::string.
std::string str = ???;
for(char& c : str) {
do_things_with(c);
}
Taken from this post.
As stated in the for statement documentation:
condition may be a declaration
With the following code to demonstrate:
int main(){
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
for (int i = 0; int x = arr[i]; ++i){
std::cout << x << std::endl;
}
}
The loop will exit once arr[i] becomes 0 and gets assigned to x causing the whole condition to evaluate to false. Why that is in more details:
a declaration of a single variable with a brace-or-equals initializer.
the initializer is evaluated before each iteration, and if the value
of the declared variable converts to false, the loop is exited.
Yes, for a zero-terminated c-string you can use the following
for(int i=0; arr[i]; i++)
because the loop will stop when it encounters the nul-terminator.
This does not work for arrays, only for zero-terminated strings. (It would also work for arrays terminated by something that converts to false, but this is quite rare IMO. Thanks #François Andrieux)
You probably want something likes this:
int main() {
char arr[] = "Hello";
for (int i = 0; char c = arr[i]; i++)
{
putc(c, stdout);
}
}
The output will be
Hello
c = arr[i] will be 0 when yolu come to the end of the string, ans thus the loop will be terminated.
BTW: for(int i = 0; strlen(arr) > i; i++) is correct but inefficient. I let you find out why as an exercise.
I am not sure if this is simplier but it is a bit different and works well for strings, not for other generic types;
You can use array[] to check for the string terminator
char array[10] = "hello";
for (int i = 0; array[i] != 0; i++)
myFunction(array[i]);
for string you can use pointer arithmetic instead
for (char *aPtr = array; *aPtr != 0; aPtr++)
myFynction(*aPtr);
I'm aware that writing this:
for(int i=0; arr[i]; i++)
will save a few microseconds over writing this:
int array_length = strlen (arr);
for(int i=0; i < array_length; i++)
I'm also aware that constructions like the first are pretty idiomatic in C, and experienced C programmers are used to seeing them.
However, in my view, the circumstances have to be very particular for saving a few cycles to be more important than writing code that other folks will understand easily. As a person who spends a significant part of his working day looking for defects in other people's code, I really appreciate expressive coding practices.
you have many options but calling the strlen is the most ineffective one (especially if you do it the way shown). arr has to be the pointer to be incremented
while(*arr)
{
/* do something */
arr++;
}
while(arr[i])
{
/* do something */
i++;
}
do
{
/* do something */
}while(*++arr);
do
{
/* do something */
}while(arr[++i]);
for(;*arr;arr++)
{
/* do something */
}
do // is you need to do somethingh with the trailing zero
{
/* do something */
}while(*arr++);
do // is you need to do somethingh with the trailing zero
{
/* do something */
}while(arr[i++]);
etc etc.

C++, return duplicate instances from an array to a string

Background to this: This is not homework, it's completely optional review for a basic c++ class. As I want to pass, I'm going through each example the best I can, This one I'm super stuck on, and have been for about three hours now.
Problem: Write a function to return a string composed of the most frequent lowercase letter found in each row of a 10 x 10 array of lowercase alphabetic chars in the range a through z.
If there is more than one most frequent character, use the one that come first alphabetically.
Use neither cin nor cout.
#include <iostream>
#include <string>
using namespace std;
string mostFrequent(char c[10][10]){
// this is the function I need to create
}
int main(){
char c[10][10] = {
'a','b','f','d','e','f','g','h','i','j',
'a','b','c','r','c','r','g','h','r','j',
'a','b','c','d','e','f','g','h','o','o',
'z','w','p','d','e','f','g','h','i','j',
'o','d','o','d','o','b','o','d','o','d',
'a','l','l','d','e','f','f','h','l','j',
'a','b','c','d','i','f','g','h','i','j',
'a','b','z','v','z','v','g','g','v','z',
'a','b','c','d','e','f','g','h','i','e',
'a','b','s','d','e','f','g','h','s','j',
};
cout << mostFrequent(c) << endl;
return 0;
}
So in research for this I found some material that allows me to count how many times a specific int or char would appear inside the array, but it doesn't quite suit the needs of the problem as it needs to return a string composed of the most frequent character. See below.
int myints[] = {10,20,30,30,20,10,10,20};
int mycount = std::count (myints, myints+8, 10);
Because it doesn't work though, I was thinking a for loop, to go row to row, I'll mostly likely need to save things into an array to count, but I'm not sure at all how to implement something like that. I even considered a caesar shift with an array, but I'm not sure where to go if that is the solution.
If I understood the task correctly, you have a matrix 10x10 and you have to create a string of length 10, where character at position i is the one that is most frequent among characters in the row i.
string mostFrequent(char c[10][10]) {
// The idea here is to find the most common character in each row and then append that character to the string
string s = "";
for (int i = 0; i < 10; i++) s += findMostFrequentCharacter(c[i]);
return s;
}
Now we just have to implement a function char findMostFrequentCharacter(char c). We are going to do that by counting all of the characters and picking the one that is most frequent (or it comes alphabetically before if there is more than one most frequent character):
char findMostFrequentCharacter(char c[10]) {
int counts[256]; // Assuming these are ASCII characters, we can have max 256 different values
// Fill it with zeroes (you can use memset to do that, but for clarity I'll write a for-loop
for (int i = 0; i < 256; i++) c[i] = 0;
// Do the actual counting
for (int i = 0; i < 10; i++) // For each character
counts[ c[i] ]++; // Increase it's count by 1, note that c[i] is going to have values between 65 (upper case A) and 122 (lower case z)
char mostFrequent = 0;
// Find the one that is most frequent
for (char ch = 'A'; ch <= 'z' ch++) // This will ensure that we iterate over all upper and lower case letters (+ some more but we don't care about it)
if (counts[ch] > counts[c]) c = ch; // Take the one that is more frequent, note that in case they have the same count nothing will happen which is what we want since we are iterating through characters in alphabetical order
return c;
}
I have written the code out of my head so I'm sorry if there are any compile errors.

C++ Add random characters into a string array

So I want to create 1000 words with a length of 5 random characters. In my main I have word[1000] but when I try to run this code, it gives me an error saying "Expression:string subscript out of range". I'm not sure why it does that because I thought string arrays were 2 dimensional? If anyone could tell me why my code is wrong I'd appreciate it. Thanks.
void createText(string w[], int seed) {
char ch;
srand(seed);
for(int i = 0; i < 1000; i++) {
for(int j = 0; j < 5; j++) {
ch = ('A' + rand() % 26);
w[i][j] = ch;
}
}
for(int i = 0; i < 1000; i++) {
cout << w[i];
}
cout << endl;
}
I suppose that the array w does not have 1000 elements, also remember that here you will get a copy of string w[]. Better would be passing a pointer to w (string* w), then You will have very clearly what is wrong. remember also that cout writes the string out untill it reaches a '\0' character, this also might be the cause. Quick session with gdb will help:
gdb program
...
run
bt full
should pinpoint Your problem. if it's some kind of IDE, learn how to debug in it. Valgrind or some other memcheck like visual leak detector or luke stackwalker will also show you some tips about bad initialization or unmentioned memory leaks.
If an array is bidimensional, you can't print its values like w[i]. You must print always keeping in mind that the array is bidimensional, which means that the output must be done like cout << w[i][j];
In addition, you're passing an array of strings as an argument, and what you're doing is add characters to every single position, which means that you won't actually have nothing but 1000 characters inserted into that string (because you actually added "one-char" strings), so you'll only put 200 words with a length of 5 characters each one. Insert strings directly, and you'll get your 1000 words, but first find a way to build strings with random characters.
Something like:
for(conditions){
for(conditions){
build a word
}
array[x][y] = string
}
I guess it is similar to what you intended to do

2D Array : Recording an ambiguous '48' after writing to it

I'm pretty new to coding and these forums so please be patient with me if I mess up.
Anyway to the question, I'm creating a 2D array to hold past guesses for my game mastermind, as a record, so the user can look back on their previous attempts. I have made a 2D array for the old guesses and it has worked fine from my small "make sure it sorta works" attempts. However, the near exact same for the old feedback (like the you got 2 colours in the right place, 1 in the wrong place and 1 completely wrong colour) it messing up,the number 48 is appearing in it from no-where and for the life, I cant work out why.
Here's my code:
const int FEEDBACK_ARRAY_ROWS = 8;
const int FEEDBACK_ARRAY_COL = 3;
int fb_cur_row = 0;
int fb_cur_col = 0;
int Feedback2DArray[FEEDBACK_ARRAY_ROWS][FEEDBACK_ARRAY_COL];
for(int i = 0; i < 3; i++)
{
Feedback2DArray[fb_cur_row][fb_cur_col] = feedback_string[i];
fb_cur_col++;
cout << feedback_string[0];
cout << Feedback2DArray[0][0];
}
fb_cur_row++;
for(int i = 0; i < fb_cur_row; i++)
{
for(int j = 0; j < 3; j++)
{
cout << Feedback2DArray[i][j];
}
}
}
For some reason this "code formatting" doesn't like 1/2 of my code so, luckily this is all I could manage but im pretty sure it has the essential stuff on there. Basically I've for the cout << feedback_string[0];
cout << Feedback2DArray[0][0];
As they should output the same thing but they're not. The first line is outputting what it should which is '0' as the counter it is based off is (as they all are) 0. However the send line outputs '48'. Any ideas why ?
feedback_string most likely is declared something like the following:
char feedback_string[3];
In other words, it is an array of char. This holds the 3 characters, which are all '0', which has a decimal value of 48 (in ASCII Code). When you perform the assignment below:
Feedback2DArray[fb_cur_row][fb_cur_col] = feedback_string[i];
You are converting an object of type char to an object of type int. This is why you see 48 printed, because when you pass an int to cout, it prints out the value the int object holds. When you pass an object of type char, it prints out the character representation of that value.
Now, if your goal is to convert the character '0' to the actual value 0, you can use the following trick which takes advantage of how ASCII codes are ordered:
Feedback2DArray[fb_cur_row][fb_cur_col] = feedback_string[i] - '0';

Read/write to file, bytes go missing, might be char overflow

I am new to programming and sometimes even the stuff I write remains mysterious to me. This is my first time asking for help on the internet.
I have a problem here and I haven't been able to solve it for some time now.
This is what I want to do:
Read byte by byte from a file into a vector, modify the bytes and write them back.
This is what happens:
All the encryption stuff seem to work, but somehow after several of these operations a part of the file goes missing.
In the byte modifying process I use char overflows, that means I add some random number to each part of my vector and write it back as a whole.
In my opinion this could be some kind of arithmetic overflow issue I don't know about.
By the way, I use Qt SDK and Windows environment, in case that helps.
Here's the code fragment:
void crypt(string * password,string filename, int sign){
vector<char> stack;
ifstream is;
is.open(filename.c_str());
char c;
for (int i = 0; !is.eof(); i++){
is >> noskipws >> c;
stack.push_back(c);
}
stack.pop_back();
is.close();
int code = 0;
double x;
char method = 0;
int var;
for (int i = 0; i < password->size(); i++)
code += password->at(i);
for (int i = 0; i < (stack.size()); i++){
// some unrelated stuff skipped
if (sign == 1)code += stack[i];
stack[i] += var*method*sign; //<----this might be the cause!
if (sign == -1)code += stack[i];
method = 0;
}
ofstream os;
os.open(filename.c_str());
for (int i = 0; i < stack.size(); i++){
os << noskipws << stack[i];
}
os.flush();
os.close();
}
Sorry for the mess in the code, I kind of wrote it for testing.
Any ideas will be appreciated.
You are opening your files in "text" mode, this can cause problems especially since your output characters will most certainly end up outside the range of printable ASCII characters. This can cause issues as on windows for example, when you try to output the value 0xD (carriage return), the library will convert that into a 0xD followed by 0XA (line feed).
So, try to open your files in binary mode like this:
os.open(filename.c_str(), ios::binary);