String Arrays/Char Arrays - c++

This is what I have to do:
A teacher has asked all her students to line up single file according to their first name. For example, in one class Amy will be at the front of the line and Yolanda will be at the end. Write a program that prompts the user to enter the number of students in the class, then loops to read in that many names. Once all the names have been read in it reports which student wourld be at the front of the line and which one would be at the end of the line. You may assume that no two students have the same name. Input Validation: Do not accept a number less than 1 or greater than 25 for the number of students.
This is what I have so far:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
int StudentNum;
cout << "How many student are in the class?\n";
cin >> StudentNum;
char sname[StudentNum + 1][25];
if (StudentNum < 1 || StudentNum > 25)
{
cout << "Please enter a number between 1-25 and try again\n";
return 0;
}
for (int i = 1; i <= StudentNum; i++);
{
cout << "Please enter the name of student #" << i << endl;
cin >> sname[i];
}
for (int output = 0; output <=StudentNum; output++);
{
cout << endl << sname[output] << endl;
}
system ("pause");
return 0;
}
Am I missing something about arrays??

You cannot create such an array because its length has to be known at compile time (i.e., it cannot be the result of an expression such as StudentNum + 1).
You can solve this issue because by the problem definition you know an upper bound for the array size, so you can use that as a compile time constant.
However, this problem can be solved without using an array at all. Read the wording carefully.
Hint for the solution without arrays: Think of the array as a single piece of paper (variable) with all the names written one after another. Not using an array then means that you have to be able to solve the problem without looking at all the names at once. How would you come to the answer if I only allowed you to see the names one by one?
Another hint: The problem is still solvable if there were several trillion students in the class (with unique names no less), i.e. more than could possibly fit in the computer's memory at any one time.

C++ array dimensions must be known at compile time (ie not dependent on user-entered variables at run-time). Use strings instead:
string sname[25];
If you were using something besides char arrays, you could also use a vector.

Think about what the problem statement is actually asking for. Your program only needs to output the first and last names alphabetically. Do you actually need to store all the names to do that?

Just for fun, here's how I would do it. Don't turn this in unless are ready to explain to your teacher how it works.
struct MinMax {
std::string min;
std::string max;
MinMax& operator+(const std::string& kid) {
if( min.empty() || kid < min) min = kid;
if( max.empty() || kid > max) max = kid;
return *this;
}
};
int main() {
int nKids;
std::cout << "How many students? " << std::flush;
std::cin >> nKids;
std::cout << "Enter students' names, followed by EOF\n";
MinMax mm(std::accumulate(
std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string>(),
MinMax()));
std::cout << mm.min << ", " << mm.max << "\n";
}

Related

Why are my char functions not doing their job?

So I am still new to C++, and I'm trying to make a program that has the user input a string, and then my functions return the string in reverse case, all lower case, and then all uppercase. Instead I just keep receiving the first letter of the string back, always uppercase. Not sure what I am doing wrong. Any suggestions?
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
char answer[255] = "";
int max = strlen(answer);
void reverse() {
for (int i = 0; i < max; i++) {
if (islower(answer[i])) {
isupper(answer[i]);
}
else if (isupper(answer[i])) {
islower(answer[i]);
}
else if (isspace(answer[i])) {
isspace(answer[i]);
}
}
cout << answer[max];
}
void lower() {
for (int i = 0; i < max; i++) {
if (isupper(answer[i])) {
islower(answer[i]);
}
else {
answer[i] = answer[i];
}
}
cout << answer[max];
}
void upper() {
for (int i = 0; i < max; i++) {
if (islower(answer[i])) {
isupper(answer[i]);
}
else {
answer[i] = answer[i];
}
}
cout << answer[max];
}
int main() {
cout << "Please enter a word, or a series of words: " << endl;
cin >> answer[max];
reverse();
lower();
upper();
system("pause");
return 0;
}
islower(char) is just a built in function to check if the char is in lowercase or not. Same goes with isupper. It does not change the case of the character.
In order to convert to lowercase/uppercase, use tolower/toupper. This would return the character in the converted case. But, it is important that you need to assign the returned value to the character itself.
Refer to this answer for some more clarity related to islower, isupper, tolower and toupper.
And now coming to the point why it's printing just the 1st character: As #user4581301 has mentioned in his comment,
"cin >> answer[max]; will read exactly one character because answer[max] is exactly one character, the first character. In C++ you have to do things in order. For example, int max = strlen(answer); will provide an answer based on what is in that string at that time. Since the string was initialized one line earlier and contains an empty string, max will be 0."
Hence your cin should be cin >> answer. BUT, this will accept the 1st word of your sentence. In order to accept all the words including the spaces, use getline() instead. And for using this, answer should be declared as string answer instead of a char array.
This is how you accept a full sentence: getline(cin,answer);
And your variable max will give an error in a few compilers as being ambiguous. This is because of the using namespace std;. to avoid this, rename max to something else, like maxlen.
And finding the length of answer: It would be better if you call answer.length() after accepting the string from user rather than doing it globally.
Your working code should look something like this:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
string answer;
int maxlen;
void reverse() {
for (int i = 0; i < maxlen; i++) {
if (islower(answer[i])) {
answer[i] = toupper(answer[i]);
}
else if (isupper(answer[i])) {
answer[i] = tolower(answer[i]);
}
else if (isspace(answer[i])) {
answer[i]=' ';
}
}
cout << "Reversed string: " + answer << endl;
}
void lower() {
for (int i = 0; i < maxlen; i++) {
if (isupper(answer[i])) {
answer[i] = tolower(answer[i]);
}
else {
answer[i] = answer[i];
}
}
cout << "Lower case string: " + answer << endl;
}
void upper() {
for (int i = 0; i < maxlen; i++) {
if (islower(answer[i])) {
answer[i] = toupper(answer[i]);
}
else {
answer[i] = answer[i];
}
}
cout << "Upper case string: " + answer << endl;
}
int main() {
cout << "Please enter a word, or a series of words: " << endl;
getline(cin,answer);
cout << "Original string: " + answer << endl;
maxlen = answer.length();
reverse();
lower();
upper();
return 0;
}
With the output:
Please enter a word, or a series of words:
ReVeRsAl UPPER aNd lower
Original string: ReVeRsAl UPPER aNd lower
Reversed string: rEvErSaL upper AnD LOWER
Lower case string: reversal upper and lower
Upper case string: REVERSAL UPPER AND LOWER
cin >> answer[max];
will read exactly one character because answer[max] is exactly one character, the character in the array at position max.
max is 0 because you have to do things in order. For example,
int max = strlen(answer);
will provide the length of answer at that time this line is reached. Since the string was initialized one line earlier
char answer[255] = "";
and contains an empty string, max will be 0. This means answer[max] is answer[0] Nothing in the code ever changes max, so it will remain 0.
OK, say we change things a little and rather than reading into a single character, we read into answer as a string. You will need to
cin.getline(answer, sizeof(answer));
because
cin >> answer;
will read one whitespace-delimited token. One word. Your stated goal is to read more than one word. istream::getline will read everything it finds into the first parameter up to the end of the line or it finds the number of characters specified in the second parameter minus 1 (in order to reserve space for the string's null terminator). sizeof(answer) is literally the size of the answer array in bytes. We're operating in byte-sized characters so the count of characters and number of bytes are the same. Extra care must be taken if multibyte characters are being used.
This seems like a good place to recommend using std::string and std::getline instead. They make a large number of problems, such as the maximum number of characters that can be read, vanish for the vast majority of cases.
I'm not going to use them here, though because the assignment likely has a "No strings" policy.
So now that we have cin.getline(answer, sizeof(answer)); reading the user's input we can work on getting the size for max. We could strlen, but we could also use istream::gcount to get the number of characters read by getline.
main now looks something like
int main() {
cout << "Please enter a word, or a series of words: " << endl;
cin.getline(answer, sizeof(answer));
max = cin.gcount();
reverse();
lower();
upper();
system("pause");
return 0;
}
Whole bunch of stuff can go wrong at this point.
using namespace std; can wreak havoc on the max because of possible collisions with std::max. In general, avoid using namespace std; The few letters it saves you from typing often are recovered by the time wasted debugging the weird errors it can introduce.
isupper(answer[i]); doesn't do anything useful as others have noted in the comments. You want
answer[i] = toupper(static_cast<unsigned char>(answer[i]));
See Do I need to cast to unsigned char before calling toupper(), tolower(), et al.? for why that insane-and-pointless-looking cast may be necessary. Thank you HolyBlackCat for bringing that to my attention.
Self assignments like
answer[i] = answer[i];
are pointless for reasons that should be obvious once you stop and think about it.
Likewise
else if (isspace(answer[i])) {
isspace(answer[i]);
}
May not be particularly useful. If answer[i] is a space, set it to a space? It's already a space. What it would do is replace other forms of whitespace, tabs and carriage returns, with a space. Newline has already been picked off by getline. Also probably needs a cast similar to the one used in the toupper example above. I'm still reading up on that.
As hinted at above,
cout << answer[max];
is not effective. It prints out one character, and if max has been fixed, answer[max] will be the terminating null. Instead print out the whole array.
cout << answer;
General suggestions:
Don't write much code at a time. Write a few lines, a function at the most, before compiling and testing. If you had tested
int main() {
cout << "Please enter a word, or a series of words: " << endl;
cin >> answer[max];
cout << answer;
}
You would have immediately seen data was not being read correctly. and fixed it before proceeding. By allowing errors to build up, you make it harder to find any one bug. You may correctly fix a bug only to find the fix undone or concealed by another bug.
Avoid using global variables. Try to place variables in the smallest possible scope. In this case, move answer and max into main and pass them to the other functions as parameters. This makes it a lot easier to keep track of who set what variable and when. It also helps prevent accidental Variable Shadowing.

Getting multiple lines of input in C++

The first line contains an integer n (1 ≤ n ≤ 100). Each of the following n lines contains one word. All the words consist of lowercase Latin letters and possess the lengths of from 1 to 100 characters.
(Source: http://codeforces.com/problemset/problem/71/A)
How would you get input from the user given n? I tried using a while loop but it doesn't work:
#include <iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int i;
while (i<=n) {
cin>>i ;
i++;
}
}
You probably meant to have something like:
#include <iostream>
int main() {
int n;
cin>>n;
int theInputNumbers[n];
for(int i = 0; i<n; ++i) {
cin >> theInputNumbers[i];
}
}
Your loop is really quite far off of what you need. What you wrote is extremely wrong such that I cannot provide advice other than to learn the basics of loops, variables, and input. The assistance you need is beyond the scope of a simple question/answer, you should consider buying a book and working through it cover to cover. Consider reading Programming Principles and Practice Using C++
Here is a working example of something approximating your question's requirements. I leave file input and output as an exercise up to you. I also make use of C++11's front and back std::string members. You would have to access via array index in older versions.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main(){
int totalWords;
cin >> totalWords;
stringstream finalOutput;
for (int i = 0; i < totalWords; ++i){
string word;
cin >> word;
if (word.length() > 10){
finalOutput << word.front() << (word.length() - 2) << word.back();
}else{
finalOutput << word;
}
finalOutput << endl;
}
cout << endl << "_____________" << endl << "Output:" << endl;
cout << finalOutput.str() << endl;
}
With that said, let me give you some advice:
Name your variables meaningfully. "int i" in a for loop like I have above is a common idiom, the "i" stands for index. But typically you want to avoid using i for anything else. Instead of n, call it totalWords or something similar.
Also, ensure all variables are initialized before accessing them. When you first enter your while loop i has no defined value. This means it could contain anything, and, indeed, your program could do anything as it is undefined behavior.
And as an aside: Why are you reading into an integer i in your example? Why are you then incrementing it? What is the purpose of that? If you read in input from the user, they could type 0, then you increment by 1 setting it to 1... The next iteration maybe they'll type -1 and you'll increment it by 1 and set it to 0... Then they could type in 10001451 and you increment by 1 and set it to 10001452... Do you see the problem with the logic here?
It seems like you are trying to use i as a counter for the total number of iterations. If you are doing this, do not also read input into i from the user. That completely undermines the purpose. Use a separate variable as in my example.

C++ text file into multi-dimensional array problems

As part of a school project, I would like to get an inventory *.txt file into an array in C++ and eventually back to a *.txt file at a later part in the program.
The text file will start out with 10 rows that will represent grocery story items and will include three columns that represent the name, price, and quantity of the items. I have been able to read from the file, even add numbers in front of each row that is displayed. Now, I would like to get the text file into a string array so that the "employee" user can make changes to items one at a time and then I can dump that array back into a *.txt file.
The code below is what I have been trying so far. I can get the count of rows in the file, but can't seem to get the columns counted or the data in the rows displayed. When I run the program, I get what appear to be 10 empty lines after it displays the rows (10) and Cols(0).
The columns in the *.txt file are normally separated by a space. I tried a tab, and tried: while(getline(invFile, lines, '\t'); which just caused the console to display what I am guessing was a memory address and then crashed.
Unfortunately, we have not gotten very far into debugging programs, and from the look of the syllabus, I don't think that will be covered very thoroughly, so I don't know how to troubleshoot any further. I have spent the last couple of hours Google-ing, and have gotten to the point that I actually need to ask for help.
The project involves a lot more than this component, but I really am stuck on this part. I am not asking for someone to do this for me, but if anyone has any idea what I am doing wrong and can point me in the best direction to get a text file into a multi-dimensional array, I would really appreciate it.
Thank you.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <array>
int row = 0;
int col = 0;
using namespace std;
int main()
{
string lines;
int x;
string textArray[2][2];
ifstream invFile;
invFile.open("inventory.txt");
if(invFile.fail()){
cerr << "The file cannot be opened!";
exit(1);
}
cout << "\n" << endl;
while(invFile.good()) {
while(getline(invFile, lines)) {
istringstream streamA(lines);
col = 0;
while(streamA >> x) {
cout << x;
textArray[row][col] = x;
col++;
}
row++;
}
}
invFile.close();
cout << "Rows: " << row << endl;
cout << "Cols: " << col << endl;
cout << "\n" << endl;
for(int i=0; i<row; i++){
for(int j=0; j<col; j++){
cout << "Line: " << i << textArray[i][j] << ".";
}
cout << "\n";
}
return(0);
}
=============================
inventory.txt:
Apples 1.25 20
Oranges 1.75 20
Kiwi 2.50 15
Pineapples 5.50 20
Tomatoes 1.50 20
Onions 2.00 20
Corn 1.80 20
Carrots 2.30 20
Milk 4.50 20
Cheese 2.25 20
I would suggest that you create a struct or class to hold the data. From each line of text, extract the fields appropriately and them to your struct. Then, keep a list of those structs using std::vector.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <array>
#include <vector>
#include <cstdlib>
using namespace std;
struct Row
{
vector<string> columns;
};
int main()
{
string line;
vector<Row> rows;
ifstream invFile;
invFile.open("inventory.txt");
if(invFile.fail()){
cerr << "The file cannot be opened!";
exit(1);
}
cout << "\n" << endl;
while(invFile.good()) {
while(getline(invFile, line))
{
Row row;
istringstream streamA(line);
string col;
while ( streamA >> col )
{
row.columns.push_back(col);
}
rows.push_back(row);
}
}
invFile.close();
cout << "Rows: " << rows.size() << endl;
cout << "Cols: " << rows[0].columns.size() << endl;
cout << "\n" << endl;
for(int i=0; i<rows.size(); i++){
for(int j=0; j<rows[i].columns.size(); j++){
cout << "Line: " << i << " " << rows[i].columns[j] << "\n";
}
cout << "\n";
}
return(0);
}
I'd like to suggest you add some print lines in the important step -- which I think also is a fast&good "debug" method. So that you can find where you wrong easily.
For example in your code, seems textArray wasn't assigned, so add some print nearby:
while(getline(invFile, lines)) {
cout <<"lines: " << lines << endl; //test enter here
istringstream streamA(lines);
col = 0;
while(streamA >> x) {
cout << "x is" << x; //test if enter here
textArray[row][col] = x;
col++;
}
row++;
}
Through the output, the lines is ok but cout << "x is" << x; wasn't printed, which means the while(streamA >>x) condition is false, why?
Go to find the library function called, std::istringstream x is int type but col 1 value is Apples, operator << will return NULL, it's unreasonable assing Apples to an int, till now, found point 1. If have to use int or float to store the numbers, use some convert API like atoi, atof.
After change x from int to string, got segmentation falut, it's obviously that textArray[2][2] is not enough to store all the information. "Out of range" is the reason of segmentation fault, so make a large array to test continue until passed.
There's a couple ways you could do this. The easiest would be to just put something like 3,10 at the top of the file, and then you know three columns and 10 rows. Since your writing this after modification, you would just need to make sure that those numbers get written correctly.
If you want to learn some more advanced methods, then your life will be easier AFTER you learn a bunch more.
If you used a vector, using something like vector< vector<string> > you could just read to a stringstream and then split the line read and put it into the vector
fstream file(...);
string tempString;
vector< vector<string> > list;
// Get a full line
while(getline(file, tempString, '\n'){
// Create a StringStream and store tempString in it for further manipulation
stringstream ss;
ss << tempString;
vector<string> tempVec;
// Get each column from this row
while(getline(ss, tempString, '\t'){
// Put each column into a vector
tempVec.push_back(tempString);
}
// Put the entire vector into our list vector
list.push_back(tempVec);
}
The benefit of this second method is twofold. First, it's very easy. I'm guessing you don't know how it works, but some easy Google searches on keywords you don't know, and you'll find out fast enough. The second is it allows (theoretically) unlimited rows, and unconstrained columns. By that, I mean one row could have 20 columns, one could have 2, and there would be no wasted space.
Note that you should NOT use the skeleton code I showed before researching it. If you don't have at least a general idea of what is happening here, then you'll just cause problems for yourself later on. I'm not going to explain everything here, because other people have done that already. Also, since you're learning this in school, you'll get to these things eventually, so you'll just be getting ahead. The one main constraint would be if your project requires arrays, in which case, my first solution would be the best option.

count specific things within a code in c++

can anyone help me make this more generalised and more pro?
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
// open text file for input:
string file_name;
cout << "please enter file name: ";
cin >> file_name;
// associate the input file stream with a text file
ifstream infile(file_name.c_str());
// error checking for a valid filename
if ( !infile )
{
cerr << "Unable to open file "
<< file_name << " -- quitting!\n";
return( -1 );
}
else cout << "\n";
// some data structures to perform the function
vector<string> lines_of_text;
string textline;
// read in text file, line by
while (getline( infile, textline, '\n' ))
{
// add the new element to the vector
lines_of_text.push_back( textline );
// print the 'back' vector element - see the STL documentation
cout << lines_of_text.back() << "\n";
}
cout<<"OUTPUT BEGINS HERE: "<<endl<<endl;
cout<<"the total capacity of vector: lines_of_text is: "<<lines_of_text.capacity()<<endl;
int PLOC = (lines_of_text.size()+1);
int numbComments =0;
int numbClasses =0;
cout<<"\nThe total number of physical lines of code is: "<<PLOC<<endl;
for (int i=0; i<(PLOC-1); i++)
//reads through each part of the vector string line-by-line and triggers if the
//it registers the "//" which will output a number lower than 100 (since no line is 100 char long and if the function does not
//register that character within the string, it outputs a public status constant that is found in the class string and has a huge value
//alot more than 100.
{
string temp(lines_of_text [i]);
if (temp.find("//")<100)
numbComments +=1;
}
cout<<"The total number of comment lines is: "<<numbComments<<endl;
for (int j=0; j<(PLOC-1); j++)
{
string temp(lines_of_text [j]);
if (temp.find("};")<100)
numbClasses +=1;
}
cout<<"The total number of classes is: "<<numbClasses<<endl;
Format the code properly, use consistent style and nomenclature and throw out the utterly redundant comments and empty lines. The resulting code should be fine. Or “pro”.
Here, I’ve taken the efford (along with some stylistic things that are purely subjective):
Notice that the output is actually wrong (just run it on the program code itself to see that …).
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string file_name;
cout << "please enter file name: ";
cin >> file_name;
ifstream infile(file_name.c_str());
if (not infile) {
cerr << "Unable to open file " << file_name << " -- quitting!" << endl;
return -1;
}
else cout << endl;
vector<string> lines_of_text;
string textline;
while (getline(infile, textline)) {
lines_of_text.push_back(textline);
cout << lines_of_text.back() << endl;
}
cout << "OUTPUT BEGINS HERE: " << endl << endl;
cout << "the total capacity of vector: lines_of_text is: "
<< lines_of_text.capacity() << endl << endl;
int ploc = lines_of_text.size() + 1;
cout << "The total number of physical lines of code is: " << ploc << endl;
// Look for comments `//` and count them.
int num_comments = 0;
for (vector<string>::iterator i = lines_of_text.begin();
i != lines_of_text.end();
++i) {
if (i->find("//") != string::npos)
++num_comments;
}
cout << "The total number of comment lines is: " << num_comments << endl;
// Same for number of classes ...
}
I'm not really sure what you're asking, but I can point out some things that can be improved in this code. I'll focus on the actual statements and leave stylistic comments to others.
cin >> file_name;
To handle file names with spaces, better write
getline(cin, file_name);
int PLOC = (lines_of_text.size()+1);
Why do you claim that there's one more line than there actually is?
if (temp.find("//")<100)
with some complicated comment explaining this. Better write
if (temp.find("//")<temp.npos)
to work correctly on all line lengths.
cout<<"The total number of comment lines is: "<<numbComments<<endl;
Actually, you counted the number of end-of-line comments. I wouldn't call a comment at the end of a statement a "comment line".
You don't count /* */ style comments.
Counting the number of classes as };? Really? How about structs, enums, and plain superfluous semicolons? Simply count the number of occurences of the class keyword. It should have no alphanumeric character or underscore on either side.
Use proper indentation, your code is very difficult to read in its current form. Here is a list of styles.
Prefer ++variable instead of variable += 1 when possible; the ++ operator exists for a reason.
Be consistent in your coding style. If you're going to leave spaces between things like cout and <<, function arguments and the function parantheses do it, otherwise don't, but be consistent. Pick one naming convention for your variables and stick to it. There is a lot about styles you can find on google, for example here and here.
Don't use the entire std namespace, only what you need. User either using std::cout; or prefix all of your cout statements with std::
Avoid needless comments. Everyone knows what ifstream infile(file_name.c_str()); does for example, what I don't know is what your program does as a whole, because I don't really care to understand what it does due to the indentation. It's a short program, so rather than explaning every statement on its own, why not explain what the program's purpose is, and how to use it?
These are all stylistic points. Your program doesn't work in its current form, assuming your goal is to count comments and classes. Doing that is a lot more difficult than you are considering. What if I have a "};" as part of a string for example? What if I have comments in strings?
Don't import the whole std namespace, only things you need from it:
using std::string;
Use a consistent naming convention: decide whether you prefer name_for_a_variable or nameforavariable or nameForAVariable. And use meaningful names: numbComments makes me associate to very different things than would numberOfComments, numComments or commentCount.
If your original code looks like this, I strongly recommend to select a single consistent indentation style: either
if ( ... )
{
...
}
or
if ( ... )
{
...
}
bot not both in the same source file.
Also remove the useless comments like
// add the new element to the vector
This is "only" about the readability of your code, not even touching its functionality... (which, as others have already pointed out, is incorrect). Note that any piece of code is likely to be read many more times than edited. I am fairly sure that you will have trouble reading (and understanding) your own code in this shape, if you need to read it even a couple of months after.
"More professional" would be not doing it at all. Use an existing SLOC counter, so you don't reinvent the wheel.
This discussion lists a few:
http://discuss.techinterview.org/default.asp?joel.3.207012.14
Another tip: Don't use "temp.find("};}) < 100)", use "temp.find("};") != temp.npos;"
Edit: s/end()/npos. Ugh.

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;
}