C++ char/string reading problem - c++

Again, I'm trying to make a simple program. It will read some kind of board, at the size of RxC. Each items on the board are letters, separated with spaces. This is a sample board:
A B C
D E F
G H I
After that, it will read an integer N, and for next N lines, read a string and process them one by one based on the given board. But now, I'm facing a problem with how to read them. Here is the code :
#include<iostream>
using namespace std;
int r,c,el; char **arr;
int main()
{
char *tes;
int n;
//start reading the puzzle
cin >> r >> c; el=r;
cout << el << endl;
arr = new char * [3*(r+c)-6];
for(int i=0;i<r;i++)
{
arr[i] = new char[c+1];
for(int j=0;j<c;j++) cin >> arr[i][j];
arr[i][c] = '\0';
}
for(int i=0;i<el;i++) cout << arr[i] << endl;
cin >> n;
while(n>0)
{
n--;
cin >> tes;
cout << tes << endl;
}
}
I don't know what's wrong with this, it's seems OK to me. However, it always get runtime errors. I'm using latest MinGW and gdb debugger. On gdb I saw something like
"received signal SIGSEGV. Segmentation
fault"
, and an 0xC0000005 error. I really have no idea what's going on here. I've tried both iostream(cin&cout) and cstdio(scanf,puts,etc.)
P.S.: I declare the variables globally, because I will process them on a different function out of the main() function. I set the size of the "height" of the array to (3*(r+c)-6), not to the normal (r) is because I will use the same array to store another strings later.

In addition to the problems already noted by others, you haven't allocated any memory for tes - it's just a dangling pointer.
Change:
char *tes;
to, e.g.:
char tes[80];

A board of size R*C needs, not very surprisingly, r*c chars of storage. I fail to understand why you're allocating the board in so many steps. A single char* board = new char[r * c]; should do it, then just keep track of where in the array your're reading.

Segmentation fault usually means you are trying to access memory which hasn't been allocated, for instance
char* mystr = (char*)malloc(3*sizeof(char));
mystr[4] = 0.0;
will (most likely) cause a seg fault because you're accessing memory which you didn't allocate (mystr goes from 0 - 2).
Are you sure you're allocating the memory correctly? I'm not sure why you have 3*(r+c)-6.

Further to unwind's answer, your array has size 3*(r+c)-6, but you are looping over values i = 0; i < r;, which depending on the values may just run out of bounds (plus it makes no sense).

Related

compare number elements in array of char

I am new to programming and I want to get an unlimited input of numbers from user, and I need to compare each number to 4 or 7; if the number is 4 or 7, I will increase counter.
The issue is that the if condition if(arr[i]!='4' || arr[i]!='7') is executed even if the number is 4 or 7.
I tried to implement another if by comparing ASCII code >>> if(arr[i]!=0x34 || arr[i]!=0x37) but this solution also doesn't work.
Can you help me to find the issue?
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
int main()
{
int counter=0;
char arr[]={};
cin >> arr;
for (int i=0 ; i<strlen(arr)-1 ; i++)
{
if(arr[i]!='4' || arr[i]!='7')
{
cout << "NO" << endl;
counter=0;
break;
}else
counter++;
}
cout << counter << endl;
if(counter==4 || counter==7)
cout << "YES" << endl;
}
Your program has undefined behavior, because this
char arr[]={};
creates an array of length zero. This is not even allowed in standard C++. If your compiler didn't complain about it, then that is because it is using a non-standard language extension.
In any case, the array has length zero. You then try to write to it with
cin >> arr;
which causes the array to be accessed out-of-bounds, no matter how long the given input is. This will cause undefined behavior and you will not have any guarantee whatsoever on how the program will behave.
Never use char arrays to store strings, especially not user input. Use std::string instead:
std::string arr;
cin >> arr;
Then instead of strlen(arr) you should use arr.size().
I am pretty sure you have further logic errors in your program (see question comments). But before you fix the program logic, you should make sure that you are writing a valid program in the first place.

String Array Causes C++ Program to Crash

I'm doing work on a multifunction program for my programming class, and one of the functions requires that an array of strings be used.
The objective is to store 10 names in an array, and then have the user enter a number that randomly determines the 'winning' name.
The only problem is that, once I execute my code, the program crashes after completing the 10 loops to get the names. That's the main thing I'm trying to identify, what's causing the crash.
The entire program is much larger, but the relevant code is shown below.
string Name1, Name2, Name3, Name4, Name5, Name6, Name7, Name8, Name9, Name10, tempName, winName;
string array[10] = {Name1, Name2, Name3, Name4, Name5, Name6, Name7, Name8, Name9, Name10};
int tempNum = 0;
int winNum;
int userEntry;
int userSelection;
for (int test = 0; test < 11; test++)
{
cout << "Enter a name: ";
cin >> tempName;
array[tempNum] = tempName;
tempNum++;
}
//The program crashes at this exact spot, right after collecting the 10th name
cout << endl;
cout << "Now choose a random number between 1 and 100: ";
cin >> userEntry;
winNum = static_cast<int>(userEntry * 3.14159 + 12.7 * 10) % 10;
winName = array[winNum];
cout << endl;
cout << "The winner of the game is" << winName << "!" << endl;
In the for loop you are trying to access to array[10] and that does not exist since array has only 10 elements, from 0 to 9. That's why your program is crashing.
Change the condition in your for loop from for (int test = 0; test < 11; test++) to for (int test = 0; test < 10; test++) and it should works.
Your array has 10 elements and and you are accessing 11 elements, 0 to 10, which is causing your program to crash. Because your code is accessing a location which doesn't belong to your program. Change the condition in for loop from test < 11 to test < 10.
Use "at" function of string class if you can, it throws an exception when you try to access out of bound subscripts.
Two problems.
One, you're instantiating an array with 10 elements then looking up its 11th element.
Firstly, change the if condition from test < 11 to test < 10.
This will solve your crash.
Secondly, your program could crash for large inputs.
When you initialize the string array, the compiler assigns a certain amount of memory to the array.
The amount of memory allocated to array is determined by the compiler.
The compiler determines the size of each of the string variables, and multiplies it by 10 to get the total size needed by the array, and allocates that much memory accordingly.
While strings can resize dynamically, arrays do not. The array has a fixed amount of memory allocated to it.
Hence, if during input of the strings that you save into the array by overwriting its indices, you could write into the array more characters than it can hold.
The amount of memory that will be allocated is implementation dependent since the default capacity of a string is implementation dependent.
A simple workaround would be to define the name strings to a large string at the beginning like string Name1 = "-------------------------";
This way the user input is most likely smaller in size that the initial value.

C++ cin to c string dynamic allocation

Trying to figure out the reasoning behind the mechanics of c strings.
char** text;
text = new char*[5];
for(int i = 0; int < 5; int++) {
cout << endl << "Enter a phrase: ";
cin >> text[i];
cout << text[i];
}
I'm not entirely sure as to why this works for the first 2 iterations, even successfully displaying them, but gets a segfault error on the 3rd iteration.
You are using uninitialized memory. You are experiencing undefined behavior.
The line
text = new char*[5];
allocated memory for five pointers but those pointers haven't been initialized to point to anything valid. Before you can use text[i] to read data, you have to allocate memory for it.
for(int i = 0; int < 5; int++) {
cout << endl << "Enter a phrase: ";
text[i] = new char[SOME_SIZE_LARGE_ENOUGH_FOR_YOUR_NEED];
cin >> text[i];
cout << text[i];
}
Then, it should work.
You've allocated memory for 5 pointers, but you are not allocating anything that those five pointers point to. Assuming that you're using a modern 64-bit CPU with 8 byte-wide pointers, your new operator allocated exactly 40 bytes, five eight-byte pointers. Their initial contents are random, uninitialized memory, and when you write to them, they get interpreted as pointers to random memory addresses, which end up being corrupted with what you've read from std::cin. You got lucky initially, and the first two iterations scribbled over some memory somewhere, but your program continued to limp along, but you won the lottery on the third try; hitting a random address that does not exist, and segfaulting.
Although you can rewrite this to do proper allocation, if you're really trying to write C++, rather than C, here, there's no reason to allocate anything. Why do you want to deal with allocating memory, when C++ will happily do it for you?
std::vector<std::string> text;
for(int i = 0; int < 5; int++)
{
std::cout << std::endl << "Enter a phrase: ";
std::string s;
if (std::getline(std::cin, s).eof())
break;
text.push_back(s);
std::cout << s << std::endl;
}

Fellow C++ programmer needs some help

// rememb-o-matic
#include <iostream>
#include <new>
using namespace std;
int main ()
{
int i,n;
int * p;
cout << "How many numbers would you like to type? ";
cin >> i;
p= new (nothrow) int [i];
if (p == 0)
cout << "Error: memory could not be allocated";
else
{
for (n=0; n<i; n++)
{
cout << "Enter number: ";
cin >> p[n];
}
cout << "You have entered: ";
for (n=0; n<i; n++)
cout << p[n] << ", ";
delete[] p;
}
return 0;
}
Now,
why is their a bracket enclosed in variable i?
p= new (nothrow) int [i];
why are their 2 for statements and what does a for statement do exactly?
Why is it deleting []p instead of the variable p?
why is their a bracket enclosed in variable i? &
Why is it deleting []p instead of the variable p?
p= new (nothrow) int [i];
Dynamically Allocates an int array of i elements .
delete []p;
Deletes the dynamically allocated array.
Basic Rules of dynamic allocation in C++ are:
If you use new to dynamically allocate memory, Use delete to deallocate it.
If you use new [] to dynamically allocate memory, Use delete [] to deallocate it.
Also, note that you are using nothrow version of the new operator, it basically returns a null if some error condition and does not throw an exception, this allows the C++ code to be compatible with the legacy c code which uses null check after memory allocations(malloc returns null on failure).
what does a for statement do exactly?
A for statement is a conditional loop construct, It keeps on executing the loop untill the condition remains true. The basic syntax of for loop is:
for(;condition;)
{
//doSomething
}
why are their 2 for statements?
The first for loop in your code gets the input from the user. It takes the input for i times.
The second for loop prints out the contents of the array.
Suggest you to pick up a good C++ book and read through the basics to understand more.
delete[] means that you are freeing an array back to the system, the no brackets for the if statement is optional and just means that the first line will be executed if true, I think you really need to learn some basics in C++ and programing in general, get a good book or google tutorials there are a lot of good ones out there
It is just C++ syntax.
new int [i] means that we want to allocate memory to store i integers.
delete [] p deletes memory bind to p. If [] are omitted, compiler assumes that p points to single instance of *p type. If instruction includes [] compiler tries to remove array of elements.

Newbie question on C++ array

I'm working through a demo program written by someone else, and I'm very confused about some of the statements they are using. I'm not very familiar with C++ (moreso with Obj-C) and I'm not sure if this is valid code or not. Take, for example, the following: (comments are mine)
int main(int argv, char** argc)
{
int perm [20]; //OK, so declare an array of ints, size = 20
for (int i=0; i < 20; i++)
perm = i; //whaaaaa??? thought you need to specify an element to assign to an array...
}
That is one example - my compiler throws an "incompatible types in assignment of 'int' to 'int [20]' error, but apparently others have been able to compile the program. Am I nuts, or is this bad code?
Here's another piece I just don't get:
int d[20] = {0}; //OK, another int array of size 20, initialized to 0's
for (int i = 1; i < n; i++)
{
d = d[i - 1]; //this I don't get - assign the array to one of its own elements??
if (invperm[i - 1] < b)
d++; //this would just increment to the next element?
}
I suspect the error is one of comprehension on my part, as if the code was bad other people would've commented on that fact...if anyone has a good explanation and/or resource I can read to understand this, I would be most appreciative!
Thanks!
*EDITED TO ADD*
In response to the answers below, I did copy/paste that code, and it looks intact to me...I can only assume when the original author posted it, it mangled it somehow. Thanks for the replies, I'm glad I had the right understanding, and I'll try and contact the author to see if there is an un-mangled copy out there somewhere!
All those examples are absolutely wrong. It looks like you lost [i] when you copied the code from wherever you got it from.
I have seen something similar with code sent over messenger programs that treat certain bits of text as emotes and replace them with images that don't get copied as text, but instead get dropped.
Your understanding is fine, that code is just entirely nonsensical.
d++; //this would just increment to the next element?
It would if d were a pointer. However since d is an array, it's simply illegal.
This is most certainly a copy/paste error.
I have succumbed to the temptation of copy/pasting code at one point during a game tech project involving Lua scripts. If the Lua script fails there is no feedback/output that indicates something is failed (which is very frustrating). After debugging for hours I realised my script was using 'smart quotes'.
Whilst this code is broken it can still teach you some things about C++.
int perm [20];
cout << endl << perm << endl;
cout << endl << &perm[0] << endl;
'perm' returns the memory address of the first element of the array. so when you are trying to assign 'i' to 'perm' in that main for loop (20 times) you will know now that you were trying to assign an integer to a memory address, hence the incompatible type error.
The second section however is verry broken and I can't discern much learning from this :P.
I added in an example program to show how pointers/arrays can be used:
#include <iostream>
using namespace std;
int main()
{
int d[20] = {0}; // 20 ints, set to 0
int * ptr = d; // points to d[0]'s memory address
for(int i = 0; i < 20; i++)
{
d[i] = 0 + i; // set array values
}
for(int i = 0; i < 20; i++)
{
// iterates through d and prints each int
cout << endl << "d[i]: " << d[i] << endl;
// dereferences the ptr to get the same int
// then incraments the position of the pointer for next time
cout << endl << "*ptr++: " << *ptr++ << endl;
}
getchar();
return(0);
}