C++ multidimension array storing strings - c++

I wish to store for example 10 words into a multi-d array. This is my code.
char array[10][80]; //store 10 words, each 80 chars in length, get from file
int count = 0;
while ( ifs >> word ){ //while loop get from file input stream <ifstream>
array[count++][0] = word;
}
when i compile, there's error. "invalid conversion from ‘char*’ to ‘char’ ". ifs return a char pointer. How can i succesffuly store into array?

As this is C++, I would use the STL containers to avoid some char* limitations. word would have type std::string, array would have type std::vector<std::string> and you would push_back instead of assigning. The code looks like this:
#include <string>
#include <vector>
std::string word;
std::vector<std::string> array;
while(ifs >> word) {
array.push_back(word);
}
This is better than char* for a few reasons: you hide the dynamic allocation, you have words with real variable size(up to memory size), and you don't have any issues if you need more than 10 words.
Edit: as mentioned in the comments, if you have a compiler that supports C++11, you can use emplace_back and std::move instead, which will move the string instead of copying it (emplace_back alone will construct the string inplace.)

You should define a pointer to array I think, that can access each value of array blocks one by one (or the way you want). You can also try dynamic allocation. Those are pointer things so then it'll be comparable easily.

word is char*(string), but array[count++][0] is store a char, you can change "array[count++][0] = word;" to "strcpy(array[count++], word);"
char array[10][80]; //store 10 words, each 80 chars in length, get from file
int count = 0;
while ( ifs >> word ){ //while loop get from file input stream <ifstream>
strcpy(array[count++], word);
}

Related

scanf function for strings

The problem is simple, the code below does not work. it says Process finished with exit code -1073740940 (0xC0000374). Removing ampersand does not change anything.
int main(){
string x;
scanf("%s",&x);
cout << x;
}
scanf() with the %s format specifier reads bytes into a preallocated character array (char[]), to which you pass a pointer.
Your s is not a character array. It is a std::string, a complex object.
A std::string* is not in any way the same as a char*. Your code overwrites the memory of parts of a complex object in unpredictable ways, so you end up with a crash.
Your compiler should have warned about this, since it knows that a char* is not a std::string*, and because compilers are clever and can detect mistakes like this despite the type-unsafe nature of C library functions.
Even if this were valid via some magic compatibility layer, the string is empty.
Use I/O streams instead.
You cannot pass complex objects through the ... operator of printf/scanf. Many compilers print a warning for that.
scanf requires a pointer of type char* pointing to sufficient storage for an argument of %s. std::string is something completely different.
In C++ the iostream operators are intended for text input and output.
cin >> x;
will do the job.
You should not use scanf in C++. There are many pitfalls, you found one of them.
Another pitfall: %s at scanf is almost always undefined behavior unless you you really ensure that the source stream can only contain strings of limited size. In this case a buffer of char buffer[size]; is the right target.
In any other case you should at least restrict the size of the string to scan. E.g. use %20s and of course a matching char buffer, char buffer[21];in this case. Note the size +1.
You should use cin. But if you want to use scanf() for whatever reason and still manipulate your strings with std::string, then you can read the C-string and use it to initialize your C++ string.
#include <iostream>
#include <cstdio>
#include <string>
using std::cout;
using std::string;
int main()
{
char c_str[80];
scanf("%s", c_str);
string str(c_str);
cout << str << "\n";
}
If you want to use strings, use cin (or getline).
string s;
cin>>s; //s is now read
If you want to use scanf, you want to have a char array (and don't use &):
char text[30];
scanf("%s", text); //text is now read
You can use char[] instead of string
include <iostream>
using namespace std;
int main()
{
char tmp[101];
scanf("%100s", tmp);
cout << tmp;
}

Finding location of character in input2 from input1

Important note: string (C++ object) and any other library such as array or vectors that could store unlimited characters cannot be used.
For my question:
We are given input 1, which is a sentence of unlimited characters. eg. Life is Beautiful.
Input 2: character who's location we have to find using the reference point (the middle character in input 1 after it is sorted and repeating characters are deleted) taken as zero. eg. fee.
An example:
Input 1: Life is beautiful
Input 2: see
Output: 2, -2, -2
Explanation: So firstly, we remove any spaces from input 1 and make all lowercase, then sort it in ascending order after which we find the reference letter (For above example, it's 'i'). We remove the repeating characters and then finally, put positions to character in input 1.
Example 2
Input 1: abcde
Input 2: aad
Output: -2, -2, 1
If the input 2 contains reference point, then the code returns zero.
Eg.
An example:
Input 1: abcde
Input 2: cab
Output: 0
The input1 is always odd and input2 is always 10 character max.
The problem I have is that I am not sure how to store these inputs without using strings, array etc. And even if I know how to store them, I cannot compare the inputs like input1[1] = input2[1] because we cannot use arrays/strings.
Is list an useful option with regards to important note?
I have mostly done it with the use of array but not sure how to approach it without the array. I tried to loop a character but it only stores the first character.
My practice code:
#include <iostream>
using namespace std;
int main() {
char input1;
for(int i =0; i < 3; i++ ) //for chacking whether the loops work or not.
{
cin >> input1;
}
cout<< input1;
char input2;
}
Please add any relevant tags.
I hope all the edits help.
KushanMehta proposed a C-ish solution. A more C++ one would be to implement a class wrapping a dynamic array of elements. In C++ it could be:
template <class T>
class MyArr {
protected:
T *arr; // a pointer to the dynamic array
size_t len; // the used length
size_t capacity; // the allocated capacity
...
As it contains a pointer to dynamic array, you cannot rely on default members, and should implement copy and move constructor and assignation operator and a destructor.
In order to be able to use all the goodies of C++ algorithm library, you should declare [c]begin() and [c]end() functions pointing to beginning of array and one past last element.
const T* cbegin() const {
return arr;
}
const T* cend() const {
return arr + len;
}
Then you need a subclass for characters implementing some methods to convert all characters to lower case and remove spaces, sort the array and remove duplicates. You should write io specializations for operator << and >> to be able to input strings from stdin and output them
The MyArr class can be used directly to store the resul value: just derive a specialization for int elements and implement the required specifications.
That may not be really easy, but you will learn C++ that way (not C)
You could do one thing to store the sentences by the use of dynamic memory for each character (sounds absurd but it is the only possible thing without actually worrying about the size of the input)
Meaning you take input till the user wants, in the meanwhile you can use malloc and realloc() for each new character, incrementing the size of your pointer to char for every new character.
(This is probably the way vector etc works on the naive level - not sure of this though)
Code snippet for the same:
#include <iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
int main() {
char temp;
char *sentence = (char*) malloc(2*sizeof(char));
int counter = 0;
while( cin>>temp ){
sentence[counter++] = temp;
sentence = (char*) realloc(sentence, (counter+2)*sizeof(char));
}
sentence[counter] = '\0';
cout<<"The sentence is"<<endl<<strlen(sentence)<<endl<<sentence;
}

C++ cin.getline to char array

I have declared an array: names[1000];
and another array, data[1000];, to store the data temporarily
and later used an ifstream to read data from an XML file.
then later, I used cin.getline(data, 300) to put the data into data[] array.
but when I assign data[] array to names[] array, an error occurs:
invalid operands of types char[1000] and char[1000] to binary operator>>
code:
char data[1000];
char names[1000];
ifstream openFile("myfile.xml");
if(!openFile)
{
cout<<"File not found! please re-enter filename"<<endl;
}
while (openFile.getline (data, 300))
{
if (data[0] == '<' && data[1] == 'n') // to only check the <name> xml tag
{
cout<<data<<endl;
data >> names;
}
}
Any idea why I cant assign data array to names array?
Thanks!
">>" operator is usually defined for streams, but data is just an array.
if you want to copy the content, use strncpy from string.h:
strncpy(names, data, 1000);
if you want to treat your string/array as stream, try stringstream.
BTW, you may want to use C++ string instead of character arrays -- it's more convenient (but not so efficient).
The operator >> is not used for assignment ! You could assign using strncpy like this
strncpy(names, data, 1000);
and add the include
#include <string.h>
Because you can't assign arrays. At all.
You may want to take a look at std::vector or std::string, which can be assigned among other cool things.
If you want to stick to char arrays, you can do the following :
std::copy(std::begin(data), std::end(data), std::begin(names));
Or (to avoid copying trash after the 300th element) :
std::copy(std::begin(data), std::begin(data) + 301, std::begin(names));

Length of a char array

I have the code like this:
#include <iostream.h>
#include <fstream.h>
void main()
{
char dir[25], output[10],temp[10];
cout<<"Enter file: ";
cin.getline(dir,25); //like C:\input.txt
ifstream input(dir,ios::in);
input.getline(output,'\eof');
int num = sizeof(output);
ofstream out("D:\\size.txt",ios::out);
out<<num;
}
I want to print the length of the output. But it always returns the number 10 (the given length) even if the input file has only 2 letters ( Like just "ab"). I've also used strlen(output) but nothing changed. How do I only get the used length of array?
I'm using VS C++ 6.0
sizeof operator on array gives you size allocated for the array, which is 10.
You need to use strlen() to know length occupied inside the array, but you need to make sure the array is null terminated.
With C++ better alternative is to simple use: std::string instead of the character array. Then you can simply use std::string::size() to get the size.
sizeof always prints the defined size of an object based on its type, not anything like the length of a string.
At least by current standards, your code has some pretty serious problems. It looks like it was written for a 1993 compiler running on MS-DOS, or something on that order. With a current compiler, the C++ headers shouldn't have .h on the end, among other things.
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::string dir, output, temp;
std::cout<<"Enter file: ";
std::getline(cin, dir); //like C:\input.txt
std::ifstream input(dir.c_str());
std::getline(input, output);
std::ofstream out("D:\\size.txt");
out<<output.size();
}
The getline that you are using is an unformatted input function so you can retrieve the number of characters extracted with input.gcount().
Note that \e is not a standard escape sequence and the character constant \eof almost certainly doesn't do what you think it does. If you don't want to recognise any delimiter you should use read, not getline, passing the size of your buffer so that you don't overflow it.

How to use length indicator in a C++ program

I want to make a program in C++ that reads a file where each field will have a number before it that indicates how long it is.
The problem is I read every record in object of a class; how do I make the attributes of the class dynamic?
For example if the field is "john" it will read it in a 4 char array.
I don't want to make an array of 1000 elements as minimum memory usage is very important.
Use std::string, which will resize to be large enough to hold the contents you assign to it.
If you just want to read in word by word from the file, you can do:
vector<string> words;
ifstream fin("words.txt");
string s;
while( fin >> s ) {
words.push_back(s);
}
This will put all the words in the file into the vector words, though you will lose the whitespace.
In order to do this, you need to use dynamic allocation (either directly or indirectly).
If directly, you need new[] and delete[]:
char *buffer = new char[length + 1]; // +1 if you want a terminating NUL byte
// and later
delete[] buffer;
If you are allowed to use boost, you can simplify that a bit by using boost::shared_array<>. With a shared_array, you don't have to manually delete the memory as the array wrapper will take care of that for you:
boost::shared_array<char> buffer(new char[length + 1]);
Finally, you can do dynamic allocation indirectly via classes like std::string or std::vector<char>.
I suppose there is no whitespace between records, or you would just write file >> record in a loop.
size_t cnt;
while ( in >> cnt ) { // parse number, needs not be followed by whitespace
string data( cnt, 0 ); // perform just one malloc
in.get( data[0], cnt ); // typically perform just one memcpy
// do something with data
}