How to use the strlen() with 2d array? - c++

I want to know the horizontal size of my 2D char array. I found strlen() for that, but it works only with a simple char array. With 2D it doesn't work. Any idea? Thanks for the answers!
char m[3][4];
for(int i = 0; i < 3; i++){
for(int j = 0; j < 4; j++){
m[i][j] = ' ';
}
}
cout << "CHAR Matrix: " << endl;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 4; j++){
cout << "[" << m[i][j] << "]";
}
cout << endl;
}
cout << "Sizeof matrix -> " << sizeof(m) << "B" << endl;
cout << "Length of Matrix strlen(m[0]): " << strlen(m[0]) << endl;
The problem is that ,,strlen(m[0]),, gives me 18. How could i get 4?

You have a few things going on. Some of the comments above help, but let's go over it.
First, if you're using C++ and you're holding strings, you should use std::string. However, your problem indicates you're just learning, so let's stick to old-school C.
What you have allocated is a 2-dimensional array of single characters. That is, you are storing in total 12 characters of data.
In C (or C++) strings are null-terminated. That is, if you store as a string "Hi", it's actually 3 characters, not two. H, I, and a zero byte that indicates the end of the string.
strlen simply counts the number of characters until the zero byte. So in my example, 2.
You don't have any 0-bytes in your array, so strlen counts until it hits a zero due to some other reason -- completely outside your array. Yikes!
So... It's a mistake to use the string methods (strlen, strdup, etc) when dealing with single characters.
Now, the safest thing would be to use a vector of std::string, as others have suggested. However, I am a firm believer in understanding the basics before taking shortcuts, and that's a shortcut.
So if what you really want is 3 strings, but you want to use old-school C, then you should actually have a 1-dimensional array of char *.
char *m[3];
m[0] = "Hello";
m[1] = "there";
m[2] = "everyone";
It would be REALLY weird to store strings the way you have, and it's considered quite dangerous to use fixed-length character buffers for holding strings. This is where the infamous buffer overrun exploits come from, the most common exploits in old school web applications.
Alternatively, you could modify your example. make m[3][5], and store a zero-byte in each row after the end of your strings. strlen() will start to work. But it's really kind of ugly.

Related

hardcoding 2D array values

Trying to insert values into a 2D array, but the output isnt giving my values, instead random letters
int myArr[8][2] = {700,730,760,790,810,840,910,1000}{0.011,0.035,0.105,0.343,0.789,2.17,20,145};
cout << myArr << endl;
system("Pause");
How should I adjust the code, or is it easier to use a text file and insert?
Numerous problems:
the array dimensions are wrong
you don't have outer braces or a comma for the nested arrays
you're trying to store double precision floating point values in an int array
you can't use cout with an entire array.
The array declaration should probably be something like this:
double myArr[2][8] = { {700,730,760,790,810,840,910,1000},
{0.011,0.035,0.105,0.343,0.789,2.17,20,145} };
and to output the contents you could do something like this:
for (int i = 0; i < 2; ++i)
{
for (int j = 0; j < 8; ++j)
{
cout << " " << myArr[i][j];
}
cout << endl;
}
Live Demo
First - you can't print the whole array just by using cout << myArr, you need to iterate over the elements of the array using a for loop.
Second - you are trying to put decimal values into an integer array which will truncate all of the decimals.
Third - Your array should be sized myArr[8][2] not myArr[2][8]. I'm surprised your compiler lets you get away with this. You should probably look into using a different compiler.
You need to iterate through each row and column, otherwise you're just printing out the pointer value of the array handle.
for (int i=0;i<8;i++){
for (int j=0;j<2;j++){
cout << myArr[i][j] << " ";
}
cout << endl;
}
system("Pause");

Length of string[] (number of elements in a string)

I want to cout my string, everything works as it should, but when the string is shown, it immediately shows me the "example_4578.exe has stopped running" error. I have noticed that the problem is in the i < str[32].length part, because when I change it to i < 3, it works without any problem. How should I solve this?
std::string str[32];
cin >> str[1];
cout << "str[1]=" << str[1] << endl;
cin >> str[2];
cout << "str[2]=" << str[2] << endl;
for (int i = 0; i < str[32].length; i++)
{
cout << str[i];
}
EDIT 1.
I've made a huge mistake. I actually want to find the "number" of elements/words in "str". In my example, I have only designed two cins. But I actually want to design a "for" loop later on, so that the user can input as many words as he wants, so if he inputs 4 words, I want that code to return those number of words to me. How should I do this? In other words, how can I find out how many elements are in "str"?
Couple of things:
C++ is 0-indexed. What this means is that std::string str[32] has indices that go from 0 to 31, and str[32] should not be accessed. This will cause a crash.
str[31].length() (which is presumably what you wanted) is the length of the last string, not the length of the array. The length of the array is 32, and your loop should read for(int i = 0; i < 32; i++).
The main problem is that you are accessing an element (number 32) that is out of the bounds (0 - 31). To solve this problem and not repeat it again in the future use a range-for loop:
std::string str[32];
for (auto s : str)
std::cout << s;
str[32].length is not what you think.
I guess you meant somthing like: length of a 32-elements array. Right?
What you've written is pointer to funciton length of 33rd element of array.
This is because the types are:
std::string str[32]; // `str` is 32-element array of `std::strings`
str[32]; // `std::string` taken from 33rd position in array `str` (arrays' indexing starts at 0)
std::string has a member function named size_t std::string::length(). When referenced by name, you get its address.
To achieve what you wanted, you'd need to write:
for (int i = 0; i < 32; i++) {
cout << str[i];
}
Unfortunately, plain arrays don't have length (or anything similar) built in. So, you'd either need to use a constant, or (better) use a container, such as std::vector.

How to get the memory address of a pointer to a char[] in c++

Full disclosure: This is homework. I'm just really confused about one part.
I have this code in a c++ program:
char * charArray = new char[100];
//fill charArray
char c = '.';
for(int i=0; i<100; i++)
{
charArray[i] = c;
c = c + 1;
}
cout <<"Char Array: " << endl;
for(int i=0; i<100; i++)
{
cout << "Type: Char # " << &charArray[i] << " = " << charArray[i] <<endl;
}
At a different point in my program I have pretty much the exact same code but instead of a char array it is a float array. When I print out the float array I get Type: Float # whatAppearsToBeAProperMemoryAddress = correctFloat#.
However although the chars are correct the address don't appear to be. The address for the char array go like this:
./0123456789<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~??????????????????
/0123456789<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz{|}~??????????????????
....
all the way to
??
?
So obviously instead of getting the address I am getting varying degrees of what should be the contents of the array. I am very confused and any pointers would be appreciated. This is my first crack at c++.
Because &charArray[i] is still a char* pointing to the ith character of the string. So it is used as a whole string. Try to cast as this:
(void*)&charArray[i]
that is the same as:
(void*)(charArray+i);

Using ASCII characters in C++ program

I've been trying to print out _ <------ this character in a 2D array... But when I
tried compiling the code, it returned some garbage numbers. I think I'm doing something wrong... can anyone please help me out to solve this problem ?
void main (){
int A[9][9];
for (int i=0; i<9; i++){
for (int j=0; j<i; j++){
A[i][j]= '_';//I am doing this part wrong.
}
}
for (int r=0; r<9; r++) {
for (int c=0; c<9; c++)
cout << setw(3) << A[r][c];
cout << endl;
}
system("pause");
}
A is an int array. So cout would try to print an integer. Try cout << char(A[r][c]);
The std::cout::operator<< operator is overloaded for several data types in order to facilitate (automagically-)formatted output. If you feed it an int, then it will print a number. If you give it a char, it will try to print it as a character. So either declare your array as an array of char, or cast the array member when printing:
cout << static_cast<char>(array[i][j]) << endl;
1. Assign the ASCII value to integer array rather than '_'. It will work even without change; but i feel it looks cleaner.
A[i][j]= 95; // try this instead of '_'
While printing, cout can print any data type without casting, but since we are looking for character to be printed, try explicit conversion.
cout << setw(3) << char(A[r][c]);
Not sure about the compiler you are using, but its a better practice to initialize the array to avoid garbage value tampering with your output

Can I do a multidimensional char array in c++?

First off, this is a "homework" question so vector libraries and string libraries are off limits. I'm trying to get to the basics of c++.
My intention with this code is to make and use an array of string arrays. A list of words in other words.
When I run this code I get a bunch of nonsense.
If there is a better way to make a list of words in c++, I would love to hear about it.
const int cart_length = 50;
const int word_length = 50;
int main()
{
char cart_of_names[cart_length][word_length];
float cart_of_costs[cart_length];
char name[word_length];
cout << "enter the name of the first item: ";
cin >> name;
for(int i=0; i<word_length; i++)
{
cart_of_names[0][i] = name[i];
}
cout << endl;
cout << "that is: ";
for(int x=0; x<word_length; x++)
{
cout << cart_of_names[0][x];
}
cout << endl;
return 0;
}
If the string entered is not 50 characters long (cart_length), then less than 50 characters will be valid in the name. You should have an if(cart_of_names[0][x]==0) break; in your second loop.
I don't exactly understand what you are looking for. Following code will help you to read and print a list of 50 words. Hope this would help you.
const int cart_length = 50;
const int word_length = 50;
int main()
{
char cart_of_names[cart_length][word_length];
float cart_of_costs[cart_length];
for(int i=0; i<cart_length; i++)
{
cout << "enter the name of the " << i + 1 << "th item: ";
cin >> cart_of_names[i];
}
cout << "that is: ";
for(int x=0; x < cart_length; x++)
{
cout << cart_of_names[x] << endl;
}
return 0;
}
Check out STLSoft's fixed_array_2d (and it's higher order siblings). There's a detailed discussion of how they're implemented for maximum performance in Matthew Wilson's Imperfect C++.
If you can't use std::string, at least look at the functions like strncpy() from C for your name copying. Also, you're forgetting that c-style strings are null terminated.
Unless you're forbidden to use STL (which would be just mean), just use std::list<std::string>. www.cplusplus.com has detailed descriptions and examples for those classes.
Otherwise, you're stuck with an array of char arrays: in that case, be prepared for a lot of buffer overflow errors. Look around on the above site for the char[] management functions (strncpy() and the like), they'll make your life a bit easier (but not a lot).
In C, the best way I found to conceptualize what you are trying to do is using an array of char*. Same effect, but if you start to work with it I believe you may find it is easier on the brain.
It looks pretty close to me. Strings in C are null-terminated, which means that the end of the string is indicated by a null character. In a sense, a string in C is really just an array of bytes.
When you do:
cout << "enter the name of the first item: ";
cin >> name;
If I enter the string "Book", in memory it'll look like something like:
|0|1|2|3|4|5..49|
|B|o|o|k|0|*HERE BE DRAGONS*
Well, really it will contain the ASCII values corresponding to those letters, but for our purposes, it contains those letters. There here be dragons is memory that that you didn't initialize, so it contains whatever garbage your platform sets it to.
So when you copy your string, you need to instead look for that 0 byte at the end of the string.
for(int i=0; name[i]!=0; i++)
{
cart_of_names[0][i] = name[i];
}
Then when you output it, you don't actually need to do it a character at a time. You can just do cout<<cart_of_names[0]. cout knows where the string ends because of that terminating null character.
If you use strcpy() instead of
cart_of_names[0][i] = name[i];
it may work better but I cringe just looking at all that code.
"If there is a better way to make a list of words in c++, I would love to hear about it."
Include #include <string> and use std::string. The std::string type is part of the C++ specification, I think.
#include <iostream>
#include <string>
int main(void) {
std::string list[7];
list[0] = "In C++";
list[1] = "you can use";
list[2] = "the `std::string` type.";
list[3] = "It removes";
list[4] = "many of the problems";
list[5] = "introduced by";
list[6] = "C-style strings.";
for (int k=0; k<7; k++) std::cout << list[k] << ' ';
std::cout << '\n';
return 0;
}