Matrix of characters in c++ [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I need matrix of characters to save 'n' subject (some subjects have 3-4 words). The user will enter 'n' number of subjects and names of subjects. I can only use CHAR, not STRING or VECTOR.
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
char matrix[n][100];
for(int i=0; i<n; i++) {
cin.getline(matrix[i][100]);
}
}

First problem with your code is that you are trying to make a variable size array with static allocation which C++ won't like (your n varies and you are trying to make char matrix[n][100]). You will need to use dynamic allocation for that.
Second problem is that getline requires an additional parameter to work (max number of characters per word you can take in, which is in your case 100).
And the third problem is that you are trying to put a whole word into a place for a single character in cin.getline(matrix[i][100]);. I'm not sure you understand why are you exactly making a matrix[n][100] so I will briefly explain.
One char stores a single character, like 'a'.
char oneCharacter = 'a';
To make a word out of those you would want few characters, so you make an array of characters. In the example I made an array of character which can take up to 5 of them.
char multipleCharacters[5];
And now you want to store a few words, so you make an array of array of characters. In the example I made an array of array of characters which can take up to 10 words of 5 characters. To make an array which size you are going to input, look up dynamic allocation from the first part of my answer.
char multipleWords[10][5];
Knowing this, can you figure out whats wrong with cin.getline(matrix[i][100]);?

As I said in a comment earlier, this is a terrible assignment. You are being asked to do several things in "odd" ways, not using and learning best practices for writing code.
My advice in general: start by separating the input, output, and "work".
Let's suppose that the code for the real lesson here is all in the "work" part. There are indeed many reasons for learning to manipulate memory this way, and C++ for writing low-level, system, or efficient code is a major part of the craft.
So, you want to arrange n words into a 2-D array of characters. Focus on (just) that, by passing in the data to be so-arranged using normal C++ code. Abstract it as a class to hold the data. Maybe this is the binary image to send to a dumb LCD on a keosk, or label printer? There may be a real reason to do something like this.
Putting in a class you can make sure memory is freed correctly; normally you want no naked new's in your code, and will use existing container types rather than low-level memory. Here, we'll use a unique_ptr of rows.
class project {
static constexpr size_t rowlen = 100;
using row = char[rowlen];
std::unique_ptr<row[]> matrix;
public:
void layout (const vector<string>& inputs);
// todo.. provide a good way to access the data
};
Now don't worry about reading from the user, especially reading directly into an odd format! That just makes this extra challenging for no reason. Take the data (presented in a normal easy-to-use way) and concentrate on doing the low-level memory manipulation chore: Allocate input.size() rows, and for each input string clamp to the maximum length and copy the characters into one row (what about the rest of the chars? Assume should be space or what?)
Clamp the length using std::max. Copy the actual characters using std::copy.
Something like this (untested; just off the top of my head):
void project::layout (const vector<string>& inputs)
{
constexpr auto N = input.size();
matrix = new row[N];
for (const size_t i= 0; i < N; ++i) {
const auto len = std::max(input[i].size(), rowlen);
auto& dest = matrix[i]; // alias the whole row
char* p= &dest[0]; // pointer to first char in the row
std::copy_n (input[i].data(), len, p);
std::fill_n (p+len, rowlen-len, ' ');
}
}
See https://en.cppreference.com/w/cpp/algorithm for details on the std algorithms. Keep that site bookmarked; it is a great way to look things up while you write code.
To do this, you need to understand how pointers work in C (and thus in C++). Also, how the same "place" can be different types: A pointer to the whole row is the same address as the first character of that row, but they are different types. So do things a little piece at a time, just as with the earlier definition of matrix.

Related

How to create a C++ multidimensional array of names with basic types

I'm trying to instantiate and easily access an array of names in C++ using basic types in contiguous memory. I'm astounded that this is extremely difficult or complicated to do in C++ WITH ONLY basic types.
For some background, I am programming a microcontroller with limited memory, modest processing power, and it is handling serial communication over a network to 36 other microcontrollers sending continuous sensor data which is uploaded to a webserver. The shorter the refresh rate of the data, the better, so I prefer basic program features.
Not that I'm saying the more complicated stuff I've looked in other forums for, like an array of strings, has worked.
In my desperation, I was able to get this to work.
char names_array[] = "Bob\0\0Carl";
printf("%s",names_array); //outputs Bob
printf("%s",names_array + 5); //outputs Carl
This is a horrible solution though. My indexing is dependent on the longest name in the array, so if I added "Megan" to my list of names, I'd have to add a bunch of null characters throughout the entire array.
What I want to do is something like this:
char names_array[2] = {"Bob","Carl"}; //does not compile
printf("%s",names_array[0]);
printf("%s",names_array[1]);
//Error: A value of type "const char *" cannot be used to
//initialize an entity of type "char" in "main.cpp"
but that didn't work.
I want to loop through the names in my list and do something with each name, so at this point, this is my best solution.
char name0[] = "Bob";
loop_code(name0);
char name1[] = "Carl";
loop_code(name1);
.
.
.
I expect there's a reasonable way to make an array of pointers, each to an array of char terminated by null(s). I must be doing something wrong. I refuse to believe that a language like C++ is incapable of such a basic memory allocation.
You can, e.g., get an array of pointers to null-terminated strings:
const char* names_array[] = { "Bob", "Carl" };
and then
std::printf("%s", names_array[0]);
std::printf("%s", names_array[1]);
The problem with your attempt
char names_array[2] = {"Bob","Carl"};
is that you declare names_array to be an array of characters. This should never compile because what the = {"Bob","Carl"} essentially attempts to do is initialize each character in that array of characters with an entire array of characters of its own. A character is just a character, you cannot assign an entire array of characters to just an individual character. More precisely, initialization of a character array from a string literal is a special case of initialization [dcl.init.string] that allows a single string literal to be used to initialize an entire character array (because anything else doesn't make sense). What you actually want would be something more like an array of character arrays. However, the problem there is that you'd have to effectively pick a fixed maximum length for all strings in the array:
char names_array[][5] = { "Bob", "Carl" }; // each subarray is 5 characters in length
which would be potentially wasteful. You can flatten a series of multiple strings into one long array and then index into that, like you did with your first approach. The downside of that, as you've found out, is that you then need to know where each string starts in that array…
If you just want an array of string constants, a more modern C++ approach would be something like this:
#include <string_view>
using namespace std::literals;
constexpr std::string_view names[] = {
"Bob"sv,
"Carl"sv
};
The advantage of std::string_view is that it also has information about the length of the string. However, while std::string_view is compatible with most of the C++ standard library facilities that handle strings, it's not so simple to use it together with functions that expect C-style null-terminated strings. If you need null-terminated strings, I'd suggest to simply use an array of pointers to strings as shown at the very beginning of this answer…
char can has only one character.
If you want to use char, you can do it like
char name0[3] = "Bob";
char name1[4] = "Carl";
char *nameptr[2] = {&name0[0], &name1[0]};
Acutally, this pretty hard.
I suggest to you, use std::string.
std::string name[2] = {"Bob","Carl"};
this code is acceptable.

String Class Manipulation

Is it possible to fix size of string variable. For example I want string variable str_new of capacity 5. P.S: I don't want to use char str_new[5]. I want to use string class. So the variable declaration should not use keyword char. Is this possible?
EXAMPLE: string str_new;
Is there any way to make sure that str_new size is fixed as 5. This question might be absurd. Please enlighten.
This code throws exception just after execution of one iteration of 'for' loop. There might be better ways to copy one string to another. But I want to copy it as mentioned below. Can someone tell me how to fix the bug, or below code cannot be fixed as its totally messed up?
string str_old = "abcde";
string str_new;
for (int i = 0; i < 5; i++)
{
str_new[i]= str_old[i];
}
However This code works fine if I do following changes
string str_new = " ";
So do I really need to explicitly initialize with blank spaces. Or there can be any other way.
You are asking two questions, and this sound very much like a homework question.
Is it possible to fix size of string variable.
There isn't any reasonable way to fix the size of a string to a size of X, and I can't think of any possible reason why you would even want to try to do so. That said, if there really is some business/homework rule that requires this, then simply check the size of the string before putting anything into it, if the size of the string plus the size of what you plan on inserting is over '5', then do something else.
For enlightenment on why, read up on the "zero one infinity rule".
This code throws exception just after execution of one iteration of 'for' loop. There might be better ways to copy one string to another.
Your code throws an exception because you are trying to replace the first character of str_new with a different character, but your object doesn't have a first character to replace.
But I want to copy it as mentioned below. Can someone tell me how to fix the bug, or below code cannot be fixed as its totally messed up?
Why do you want to use that for loop? That again leads me to believe this is some sort of homework assignment, because this is definitely not a good way to copy one string into another. A simple assignment is all that is necessary:
string str_new = str_old;
But I get it, you want to use the for loop and you don't even want a loop based on the actual size of str_old. Here you go:
string str_old = "abcde";
string str_new(5, 0);
assert(str_old.size() >= 5);
for (int i = 0; i < 5; ++i) {
str_new[i]= str_old[i];
}
The above code creates a string str_new that has five elements in it that are all equal to 0. It then checks to make sure that str_old actually is 5 characters long. Then it replaces each 0 with a copy of the character at the corresponding position in str_old.
Don't put that kind of code in a real program, but if it satisfies the homework assignment, then go for it.
Why don't you do
string.reserve()
If you want initialized a string of the right capacity, you can do
string.resize()
void resize (size_t n);
void resize (size_t n, char c);
Resize string
Resizes the string to a length of n characters.
void reserve (size_t n = 0);
Request a change in capacity
Requests that the string capacity be adapted to a planned change in size to a length of up to n characters.
If n is greater than the current string capacity, the function causes the container to increase its capacity to n characters (or greater).

Dynamically allocated strings in C

I was doing a relatively simple string problem in UVa's online judge to practice with strings since I've been having a hard time with them in C. The problem basically asks to check if a string B contains another string A if you remove the 'clutter' and concatenate the remaining characters, for example if "ABC" is contained in "AjdhfmajBsjhfhC" which in this case is true.
So, my question is how can I efficiently allocate memory for a string which I don't know its length? What I did was to make a string really big char Mstring[100000], read from input and then use strlen(Mstring) to copy the string the a properly sized char array. Something like :
char Mstring[100000];
scanf("%s",Mstring);
int length = strlen(Mstring);
char input[length+1]={0};
for(int i = 0; i<length;i++){
input[i]=Mstring[i];
}
Is there a better/standard way to do this in C? I know that C does not has a great support for strings, if there is not a better way to do it in C maybe in C++?
If you have the option of using C++ (as you mentioned), that is going to make your life a lot easier. You can then use a STL string (std::string) which manages dynamically sized strings for you. You can also drop the old scanf() beast and use std::cin.
Example:
#include <iostream>
#include <string>
void main()
{
std::string sInput;
std::getline(std::cin, sInput);
// alternatively, you could execute this line instead:
// std::cin >> sInput;
// but that will tokenize input based on whitespace, so you
// will only get one word at a time rather than an entire line
}
Describing how to manage strings that can grow dynamically in C will take considerably more explanation and care, and it sounds like you really don't need that. If so, however, here is a starting point: http://www.strchr.com/dynamic_arrays.

How to clear the buffer in a (char*)?

In my program I have a char* buffer which is being used inside a thread sequence which carries text from one function into another, but the text is different through the run-time in my program. The question that I am asking is, which function can I use to clear the previously used text out of the char* ?
For example, I have the following code:
int GameUtils::GetText(char *text)
{
for(int i=0; i<LINES_OF_TEXT; i++)
{
if(line[i][0]!=0)
{
strcpy(text, line[i]);
MessageBox(0, text, 0, 0);
line[i][0]=0;
return 1;
}
}
return 0;
}
line is defined as such: char GameUtils::line[2][32];
When the messagebox is output on the screen (while code is executed). I get some random junk characters in the text field. Can anyone tell me why this is?
Also! Note that line is assigned as stated in my previous question.
The function which assigns line is:
for (int x=0; x<((int)(strlen(szLine)+1)); x++)
{
if (szLine[x]==' ' || szLine[x]=='\0')
{
m=x;
for (y=0, z=n; z<m; y++, z++)
{
line[w][y]=szLine[z];
}
n=x+1;
w++;
}
}
The above function simply takes a parameter szLine[512] which is passed from my game interface and splits up the line assorting each space as a new parameter.
As an example, if inside the game the user states the line:
/msg <player> <message>
The function would assign each separate word to the line variable, respectively.
Such that, after the function is finished. line would look like
line[0] = /msg
line[1] = <player>
line[2] = <message>
So my question overall is as follows. Am I taking the cleaniest/most appropriate approach at this problem? If not, can anyone show me a better way to approach this problem? Also, can anyone explain to me why I am getting junk characters in the text parameter when the messagebox executes?
EDIT
After viewing the preview of my submitted question; I noticed I have defined char GameUtils::line[2][32] as a 2-dimensional array. I had done this earlier to test. I now understand this could have been the cause to my problem. Can anyone suggest me a replacement for this if I don't know the exact amount of parameters that could be inputted into this variable. The user can issue different requests each time like "/help ", "/msg ", "/whois ", "/create "...
When memory is allocated it isn't zeroed first (at least when using malloc, calloc - however, does zero memory first).
To clear a buffer in C (rather than C++), you have a few options:
Allocate the buffer using calloc instead of malloc.
Use Win32's ZeroMemory function
Use memset, like so: memset( buffer, 0x00, BUFFER_SIZE );
However you're clearly using C++, so you should use the standard library and C++ idioms rather than C-style things, that means using std::string instead of char*, and if you have to use buffers directly then the C++ way of zeroing (or filling) an array or buffer is std::fill.
First off, I would avoid using double dimensional arrays if you can avoid it. Maybe look into std::string:
http://www.cplusplus.com/reference/string/string/
As for why a char array might have "random junk" in it, when you allocate a buffer in C++, it always has data in it. You have to manually set the data to 0 if you want it to be empty. So when you first allocate an array, it might be a idea to zero out all the values first.

find repeated words number in c++

is there anyway to find out how many times a word repeated in a text .
the text is in character arrays (char[])
text = this is a book,and this book
is about book.
word = book
result = 3
Because this is clearly homework and not tagged as such, I'll give you a solution you clearly can't submit as your assignment because your teacher will know you got it on the internet.
There were no requirements such as ignoring punctuation, so I've allowed myself to write a version that only works for clearly separated words and thus inserted spaces in your sample text string.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
// Count clearly separated occurrences of `word` in `text`.
std::size_t count ( const std::string& text, const std::string& word )
{
std::istringstream input(text);
return (std::count(std::istream_iterator<std::string>(input),
std::istream_iterator<std::string>(), word));
}
int main ( int, char ** )
{
const char text[] = "this is a book , and this book is about book .";
const char word[] = "book";
std::cout << count(text, word) << std::endl;
}
Output:
3
You might want to implement this using std::string and here is a sample for you to start from.
The simplest way would be to loop through the string, counting the number of times that you find the word that you're looking for. I'm sure that you could use a function in <algorithm> to do it fairly easily, but if you have to ask whether it's possible to do this in C++, I wouldn't think that you're advanced enough to try using the algorithm library, and doing it yourself would be more instructional anyway.
I would suggest using std::string though if you're allowed to (since this question does sound like homework, which could carry additional restrictions). Using std::string is easier and less error-prone than char arrays. It can be done with both though.
It is possible.
You have an array of characters. Try to do the search on a piece of paper, character by character:
First character is a T. This is not a b, so it can't be the first character of "book"
Second character is a h, so again, it is not b...
[...]
The next character is a b... Oah, this could be it. Is the next character a o? YES!!! And then next another o???... etc. etc..
When you can do it this way, you will be able to use C++ to do it.
Remember that you can access the n-th character in an array by using the [] operator:
char c = array[5] ; // c is the 6th character in the array
Now, going toward the C++ way would be, at first, to use a std::string instead of an array of chars, and use the strings methods. Google for std::string methods, and I guess you should find somes that you could use...
So you should manage to write some code that will iterate each character until the end
I guess this should be more than enough.
The point of your homework (because everyone here knows this is a homework question) is more about searching for the solution than finding it: This is not rote learning.
I doubt anyone on Stack Overflow remembers the solution to this classical problem. But I guess most will know how to find one solution. You need to learn the "how to find" mindset, so get your compiler and try again...
P.S.: Of course, if you know little or nothing of C++, then you're screwed, and you could start by Googling some C++ Tutorials.