I have trouble understanding the following code,
static char s[N][N];
int i = 0;
while( gets(s[i]) )
{ some loop, where i gets incremented }
considering the array is of N dimensions, then what happens when
gets(s)
is called? How can it store the entire string in the s[i] element? It feels like s[i] should be equal to the first char of the input, and not the entire string. And what happens when it loops with more input? The point is to have it stored as
[char, char, char, char]
[char, char, char, char, char]
[char, char, char, char, char, char]
... and so forth
which it seems like the code is currently doing. But I don't understand how.
EDIT #1
A lot of people suggested against using gets(), but why would gets() not be appropriate when there can be no illegal input and I want to store the characters as elements in an array and not as a string?
The s[i] element is an array of characters since s is an array of arrays. An array of characters can be used to store a string by using a zero character (called a "nul") to mark the end.
The code above is storing the string but with a numbered index.
But storing that number index in the first dimension of the array.
Think of it in this way, I want to store 10 strings of max size of 256 char:
int main()
{
char s[10][256];
for (int i = 0; i < 10; i++ ) {
gets(s[i]);
}
for (int i = 0; i < 10; i++ ) {
cout << s[i] << endl;
}
}
cout << s[1][2] << endl;
Note: for the last line in the code above it would output the second entry (we ordered everything from 0-9) and third character of the string at that entry.
Thus, if my entry was test2 then the output would be 's'.
Note: It would be incorrect to call gets(s) as it will not compile and is not the intention of the code.
gets() call has some features that can land you into a buffer overflow problem if the input is not monitored.
Example:
int multi_array[2][2] = {{2,3,4},
{7,8,9},
{1,5,0}};
Array[n][m]
Gets
First position Array[0][0]
Second position Array[0][1]
Position 0,1 is 3
Position 1,2 is 9
Position 2,2, is 0
Related
Trying to fill an array using a pointer so each index of array contains its' index. The output I am currently getting is this +DD;D;DD. Could someone explain where I am going wrong on this? Thanks.
#include <iostream>
using namespace std;
int main()
{
int NUMBER_ELEMENTS;
cout << "Enter number of elements: ";
cin >> NUMBER_ELEMENTS;
short array1[NUMBER_ELEMENTS];
short *arrPtr;
arrPtr = array1;
short i = 0;
while(i < NUMBER_ELEMENTS)
{
*arrPtr = i;
arrPtr = arrPtr + 1;
cout << "+" + array1[i];
i++;
}
}
Problem 1: The length of an automatic array can not be given at runtime. It must be known at compile time. In order to create an array with dynamic length, you can use std::vector instead.
explain how this is a variable length array?
You can input different values in different executions of the program. Therefore the length varies. Even the value staying the same is by itself not sufficient. The expression used the array length must be a compile time constant expression.
Problem 2: "+" + array1[i] doesn't do what you probably think it does.
The string literal is an array of characters. array1[i] is an integer. When you add an integer to an array using the plus-operator, the array decays to a pointer to first element of the array, and the the pointer is incremented by number given as the operand.
Therefore "+" + 0 increments the pointer by zero places, so the string printed in the first iteration is "+". "+" + 1 increments the pointer by one places. After the + character, there is only the null terminator, so the printed string is empty. After that iteration, the later iterations overflow the array, and the behaviour of the program is undefined.
I passed an array of characters to a function and used a pointer to point at the first element of the array.
How do I point through each element of the array and delete the characters I don't want.
I am trying not to use brackets and other variables just this pointer and maybe another one.
Thanks.
if you really want to do it in your way, you have to declare a new array of characters and then count the element of the characters that you want to be left on the array by iterating on the array through your pointer, that count will be the size of the new array.
example:
char b[] = "acbbca";
char* p = &b[0];
int oldsize = 6;
int newsize = 0;
for ( int a = 0; a < oldsize; a++ )
{
if(*p!='b')
newsize++; // increment the newsize when encountered non-b char
p++;
}
in the snippet above, you count the number of non-b characters, so it will be the size of the new array.
p = &b[0]; // point again to the first element of the array.
char newone[size]; declare the new array that will hold the result
int ctr = 0;
for ( int a = 0; a < oldsize; a++ )
{
if(*p!='b')
{
newone[ctr] = *p; //store non-b characters
ctr++;
}
p++;
}
in the snippet above, it stores all non-b characters to the new array.
another way is to use std::string.
std::string b = "aabbcc";
b.erase(std::remove(b.begin(),b.end(),'b'),b.end());
Since arrays cannot be resized, there really is no such thing as "removing elements". To actually remove elements, you would need to use a container such as std::string where elements can actually be removed.
Given this, let's assume you can only use an array, and that "removal" means to move the removed values to the end of the array, and then point to where the removed elements start. The STL algorithm function std::remove can be used to accomplish this:
#include <iostream>
#include <algorithm>
int main()
{
char letters[] = "aabbccbccd";
// this will point to the first character of the sequence that is to be
// removed.
char *ptrStart = std::remove(std::begin(letters), std::end(letters), 'b');
*ptrStart = '\0'; // null terminate this position
std::cout << "The characters after erasing are: " << letters;
}
Output:
The characters after erasing are: aaccccd
Live Example
The std::remove just takes the character you want to remove and places it at the end of the array. The return value of std::remove is the point in the array
where the removed elements were placed. Basically the return value points to where the discarded elements start (even though the elements aren't actually discarded).
So if you now write a function to do this, it would probably look like this:
void erase_element(char *ptr, char erasechar)
{
char *ptrStart = std::remove(ptr, ptr + strlen(ptr), erasechar);
*ptrStart = '\0'; // null terminate this position
}
Live Example 2
We pass a pointer to the first element, and use the strlen() function to determine how long the string is (the function assumes the string is null-terminated).
So I found this code on the internet, but as I'm not that familiar with C++. I found difficult to understand this: how does a vector suddenly becomes a matrix?
int main(){
int n;
string v[MAX];
cin >> n;
for(int i=0;i<n;i++)
cin >> v[i];
for(int i=0;i<n-1;i++){
int y1,y2;
y1=v[i].size();
y2=v[i+1].size();
for(int j=0; j<y1 && j<y2 ;j++)
if(v[i][j]!=v[i+1][j]){ // here <-
int x1,x2;
x1=(int) v[i][j]-'A';
x2=(int) v[i+1][j] - 'A';
m[x1][0]=true;
m[x2][0]=true;
m[x1][x2+1]=true;
break;
}
}
string v[MAX];
is an array of std::string (presumably - this is one reason to avoid using namespace std;. How do I know what type of string it is?).
You can access elements of an array with []:
int someInts[5];
someInts[3]=1000; // sets the 4th int (counting starts from 0)
You can also access characters in a std::string with []:
std::string name("chris");
std::cout << name[3]; // prints 'i'
So you can access the letters in an array of std::strings with two sets of []:
std::string names[10]; // 10 names
names[3] = "chris"; // set the 4th name
std::cout << names[3][1]; // prints 'h'
// ^ access letter in string
// ^ access string in array
Here is a self-explanatory example
int main()
{
std::string name;
name = "test";
for(int i = 0; i<4; i++)
std::cout<<name[i]<<std::endl;
std::cout << "Hello, " << name << "!\n";
}
It will print
t
e
s
t
Hello, test!
So, an array of strings is actually a 2D array of characters, that you called a matrix.
string v[N] is an array of string, string itself is an array of chars.
Since, as the commentor pointed out, there are neither vectors or matrices in the code you gave, I'll make a couple assumptions:
By "vector", you mean "array"
You think that double square brace operators ([][]) indicate a matrix.
If those are both true, I can explain what you're seeing:
string[5] strings = { Some Strings... }
//The first string in the array
string string1 = strings[0];
//The first letter of the first string
char char1 = string1[0];
//The above is the same as:
char char1Again = strings[0][0];
In the line above, the first square bracket operator returns the first string in the array. The second square bracket operator is then applied to that string, which returns the first character of that string.
This works because both arrays and Strings (which are really arrays themselves deep down) implement the square bracket operator to access their internal elements by index.
Technically, in a convoluted way, you could call this a matrix, but "2D array of characters" would be more appropriate.
Why does c-string length matter when using for loops? Is there an issue with the termination character '\0'?
The following code sends the for loop into a crazy loop that crashes the compiler:
#include <iostream>
#include<cstring>
using namespace std;
int main()
{
char c[] = "charac";
int i;
for (i=0; i < 8 ; i++)
{
cout << c[i] << endl;
}
return 0;
}
By adding a 't' to my c-string, the code runs perfectly fine:
char c[] = "charact";
int i;
for (i=0; i < 8 ; i++)
{
cout << c[i] << endl;
}
In your first version, there is no character c[7]. You have 7 characters in the array, 6 characters of string and 1 null terminator:
Array: c h a r a c \0
Indices: 0 1 2 3 4 5 6
Attempting to access anything beyond that is undefined behavior.
In your second version, assuming the code you're running has the t you forgot to put in the posted version, the array has 8 characters, and the loop stays within the bounds of the array.
You have a string of length 7 (6 + null terminator), and are attempting to access an 8th element. This will result in undefined behavior.
I think that you are stepping past the end of the end of your character array. By adding the extra character, your string is now 7 characters long so the i<8 test works.
You are index past the end of the array. C starts indexing at zero so the last index of a six character string is five. If you include the null terminator then you have six but you are accessing the seventh array position.
c[7] doesn't exist for "charac" as c[6] is the null terminating character. But when you change it to "charact" then c[7] becomes the null terminating character so it runs fine.
A few things.
When I declare my struct with a member array of size 3, wouldn't that mean that array has 4 elements? 0, 1, 2, 3? Why them, when I try to insert the characters A, B, and C, it tells me initializer-string for array of chars is too long [-fpermissive]?
#include <iostream>
using namespace std;
struct Student {
double no;
char grade[3];
};
int main() {
struct Student harry = {975, "ABC"};
}
When I print the address of a specific index of a character array I get the following results from the following code:
struct Student {
double no;
char grade[4];
};
int main() {
struct Student harry = {975, "ABC"};
for (int i = 0; i < 4; i++)
cout << "h.g[" << i << "]" << harry.grade[i] << endl;
for (int i = 0; i < 4; i++)
cout << "h.g[" << i << "]" << &harry.grade[i] << endl;
}
Results:
h.g[0]A
h.g[1]B
h.g[2]C
h.g[3]
&h.g[0]ABC
&h.g[1]BC
&h.g[2]C
&h.g[3]
Why does the first index print ABC, and then BC, and so forth instead of each character separately like the first loop?
No, declaring an array like T arr[3] gives you an array with 3 elements, not 4. The 3 in the declaration is the size of the array. Indices start at 0, so the indices for the elements are 0, 1, and 2.
The string literal "ABC" gives you an "array of 4 const char" where the last element is the null character. Your program is ill-formed if you attempt to initialise an array with a string literal that has too many characters:
There shall not be more initializers than there are array elements.
In the first loop you are getting each character of the array and printing it out. When you print a char you get only that char as output.
When you take the address of an element of the array, with &harry.grade[i], you get a char*. When you output a char*, the I/O library treats it as a C-style null-terminated string. It will output from that character to the first null character it finds. That's why you get the character at position i and the characters following it.
When I declare my struct with a member array of size 3, wouldn't that mean that array has 4 elements? 0, 1, 2, 3?
No, it means it has three elements, which you can access with indices 0,1,2.
Why does the first index print ABC, and then BC, and so forth instead of each character separately like the first loop?
You are accessing beyond the bound of an array, which leads to undefined behaviour. That means anything could happen. You are also assigning a size-4 character array, "ABC", to a size-3 array. So you have out of bonds read and write access.
The 4th element in char array "ABC" it the null-termination \0. When you print the address of any element of a char[N] with std::cout, it will see a char*, which it interprets as a null-terminated string. So it will print characters up to the null termination. So if you print from the beginning, you get A, b, C. If you print from the second element you get B,C, and so on.