multidimensional string c++ - c++

I'm writing a function that has a 2D array of strings as input parameter. I initialized the string, passed it to the function but when I tried to print the array nothing happened. It says that the length of the array is 0. All my functions are stored in a header file. Here's my code:
#include<iostream>
#include<string>
#include<iomanip>
using namespace std;
int c,i,j,fx,fy;
int color,fields,rows,anim,speed;
string opt[5][50];
string popt[5][50]={
{"caption","asdf","safd","asf"},
{"caption1","dsafa","asdf","asdf"},
{"caption2","asdf","asdf","asdfas"},
{"caption3","sadfa","asdfs","fasdfa"}};
void ini(int focus_text_color, int n_fields,int n_rows, string options[][50], bool animation=false, int animation_speed=10)
{
color=focus_text_color;
fields=n_fields;
for(i=1;i<fields+1;i++)
{
for(j=1;j<rows+1;j++)
{
opt[i][j]=options[i][j];
}
}
}
int drawh()
{
system("cls");
for(i=0;i<fields;i++)
{
for(j=0;j<rows;j++)
{
cout<<opt[i][j]<<setw(opt[i+1][j].length()+5);
}
}
return 0;
}
void main()
{
ini(LIGHTRED,4,4,popt);
drawh();
}
NOTE: This is a part of the code so I haven't tested it, and sorry for my bad English :D

Apart from #Oli's comments. To make it simpler, you can pass an array by reference. See below example:
template<unsigned int ROW, unsigned int COL>
void ini (string (&s)[ROW][COL]) // psuedo code for 'ini'; put extra params to enhance
{
ini(s, ROW, COL);
}
Now, template ini() provides a wrapper to actual ini() which calculates the row/column of an array at compile time. Usage is very simple:
string s[10][5];
ini(s); // calls ini(s,10,5);
Your loop should start from dimension 0 and not 1 for copying. Check my approach and modify your code.
for(int i = 0; i < ROW; i++)
for(int j = 0; j < COL; j++)
s1[i][j] = s2[i][j];
Also there are many problems in your code due to passing wrong dimensions (e.g. passing 4 as dimension while calling ini(), when it should be 5).

The reason why you don't get any output is that you don't initialize the global variable rows, so it stays at 0. Your init function should be:
void ini(int focus_text_color, int n_fields,int n_rows, string options[][50], bool animation=false, int animation_speed=10)
{
color=focus_text_color;
fields=n_fields;
rows = n_rows; //-- ADDED LINE
....

Related

homework arrays and pointers of c ++

In this question, firstly, you have to write two functions:
new_array (char** a, int n, int m): create a two-dimension matrix of characters whose size is m*n.
del_array (char** a, int n, int m): delete a two-dimension matrix of characters whose size is m*n.
After that, you use two above functions to perform the following task:
You are given a big image with size M*N and some small images with size m*n. Each image is presented by a matrix of characters with its size. Your task is finding the number of positions which each small image occurs in that big image.
Input file: image.inp.
The first line of the input file contains two positive integers M and N which are respectively the height and the width of the big image.
Each line 2...M+1 consists of N characters (a...z, A...Z) which describe a row of the big image.
Subsequently, there are some small images which you must find the big image. Each small image is written in the formation of the big image. Specially, there is a line having m = 0 and n = 0, you have to end your finding process.
Output file: image.out.
For each small image in the input file, you must write a number which presents the number of positions which that small image occurs in the big image.
image.inp image.out
4 4 3
Aaaa 1
Aaaa
Aaab
Aaaa
2 2
Aa
Aa
2 2
aa
ab
0 0
I did this:
file header: image.h:
#ifndef _IMAGE_H_
#define _IMAGE_H_
using namespace std;
void new_array (char** , int , int );
void del_array (char** , int , );
bool small_image(char**,char**,int,int,int,int)
int count_small_image(char** , char** , int ,int ,int ,int );
#endif
file image.cpp:
#include<iostream>
#include "image.h"
#include <fstream>
using namespace std;
void new_array(char** a, int n,int m)
{
ifstream inStream;
inStream.open("image.inp");
a=new char* [m] ;
for(int i=0; i<m; i++)
{
a[i]=new char[n];
for(int j=0;j<n; j++)
inStream>>a[i][j];
}
}
void del_array(char** a,int m)
{
for(int i=0;i<m ;i++)
{
delete [] a[i];
}
delete [] a;
}
bool small_image(char** a,char** b, int i,int j,int p,int q)
{
for(int u=i;u<i+p;u++ )
{
for(int v=j;v<j+q;v++ )
{
if(a[u][v]!=b[u-i][v-j]) return false;
}
}
return true;
}
int count_small_image(char** a,char** b,int m,int n,int p, int q)
{
int COUNT=0;
for(int i=0;i<m;i++ )
for(int j=0;j<n;j++ )
{
if(a[i][j]==b[0][0])
{
if((m-i+1)>=p && (n-j+1)>=q)
{
if(small_image(a,b,i,j,p,q)==false) break;
else COUNT++;
}
}
}
return COUNT;
}
file main_count_small_image.cpp:
#include <iostream>
#include "image.h"
#include <fstream>
using namespace std;
int main()
{
ifstream inStream;
inStream.open("image.inp");
ofstream outStream;
outStream.open("image.out");
int m,n,p,q;
char** a;
char** b;
inStream>>n>>m;
new_array(a,n,m);
inStream>>q>>p;
new_array(b,q,p);
int c;
c=count_small_image(a,b,m,n,p,q);
outStream<<c;
del_array(a,m);
del_array(b,p);
return 0;
getchar();
}
But, I get:
[error]: has stopped working ...
This is a simple bit of code best stepped through with a debugger. The OP will learn a lot more tracing the execution low than they will from being handed a canned answer.
Brute force works, but a previous question has an answer suggesting better approaches. See How to detect occurrencies of a small image in a larger image? .
The new array method is implemented incorrectly. Its inability to return the built array has been covered already so I'm skipping it. Nowhere in the specification does it say the new_array should read in the data from the file. Further, reopening the file will require the new stream to tart at the beginning and reread m and n before getting to the image data. This is not taken into account.
The lack of descriptive variable names makes this program difficult to read and is a disincentive to assisting the OP. Likewise the lack of rational indentation and braces use. The program by its appearance seems to ask the reader not to render assistance.
In count_small_image given the call
count_small_image(a,b,m,n,p,q);
The two for loops set up small_image for out-of-range array access. I believe that is that this is trying to prevent.
if((m-i+1)>=p && (n-j+1)>=q)
Maybe it does, but it's a convoluted and clumsy way to do it. Remember: Code not written has no bugs. Instead, try something along the lines of
for(int m = 0; m < largeMaxM - smallMaxM; m++)
{
for(int n = 0; n < largeMaxM - smallMaxN; n++)
Where smallMaxM and smallMaxN are the m and n bounds of the small image and largeMaxM and largeMaxN are the m and n bounds of the large image.
Small count is also overly complicated. Sorting it out so that it is based on iterating through the small image eliminates the cruft. descriptive variable names also makes the function much more readable.
bool small_image(char** a,char** b, int offsetM,int offsetN,int maxM,int maxN)
{
for(int m = 0; m < maxM; m++)
{
for(int n = 0; n < maxN; n++)
{
if(a[m+offsetM][n+offsetN]!=b[m][n]) return false;
}
}
return true;
}
I'm operating on tablet without a compiler, so forgive me if I'm off by one.
You've been told wrong (or you've misunderstood what you were told). Rewrite your code like this
char** new_array(int n, int m)
{
char** a;
...
return a;
}
int main()
{
...
char** a = new_array(n, m);
etc.
You should read up how functions can return values (including pointers). And also read up on how pointers can be used to implement arrays.

how to import text file into structs C++

I'm trying to import data from a text file into structs for use as i don't really want to import them into seperate arrays.
I keep getting "error: expected primary-expression before '[' token" on each getline, i'm terrible at C++ and basically using what C skills i have to try and make sense of this. What am i doing wrong?
#include <stdio.h>
#include<fstream>
#include <cstdlib>
#include <iostream>
#include "Ladybird.h"
using namespace std;
typedef struct managerImport{
int gridSizeA;
int gridSizeB;
int aphidCount;
int aphidPos;
int ladyCount;
int ladyPos;
struct managerImport *next;
};
void importData(managerImport[]){
ifstream manager;
manager.open("Manager.txt");
if (!manager.fail()){
//loops the 2d array
for (int i = 0; i < 1; i++)
{
getline(manager, managerImport[i].gridSizeA, managerImport[i].gridSizeB);
}
//loop the lady bird count
for (int i = 1; i < 2; i++)
{
getline(manager, managerImport[i].ladyCount);
}
//loops the lady bird coordinates
for (int i = 2; i < 10; i++)
{
getline(manager, managerImport[i].ladyPos);
}
for (int i = 10; i < 11; i++)
{
getline(manager, managerImport[i].aphidCount);
}
//loops the lady bird coordinates
for (int i = 11; i < 19; i++)
{
getline(manager, managerImport[i].aphidPos);
}
}
manager.close();
}
int main() {
//importing the manager text file
importData;
}
Did you name the argument in the function?
void importData(managerImport[]) just says you have a function importData that takes an array of type managerImport (your struct).
Edited for clarification:
Imagine I write this code:
int increment(int) { return int+1; }
What I've done is hand the compiler a function that takes an argument "int". Is "int" a type or the name of my argument? This obviously won't compile since the argument has to have both a type and a name (so even if I want want to name my argument "int" (not advised), I still need to supply a type which says what "int" actually is (type-wise). Is it a long, a string, an unsigned char? Assuming I meant to actually accept an int, add 1, and return the incremented value (an int), this is what I should have written:
int increment(int i) { return i+1; }
So, in your case, you have:
void importData(managerImport[]) { ... }
Obviously, you're meaning to accept an array of managerImport, but you haven't given that array a name. Try this:
void importData(managerImport foo[]) { .. }
Also, unless you really need a c-array, you might try using a vector or an C++ array (std::array).
The function getline does not translate text into integers. It simply copies text without translations.
for (int i = 0; i < 1; i++)
{
getline(manager, managerImport[i].gridSizeA, managerImport[i].gridSizeB);
}
Your getline function call translates to getline(stream, int, int);.
You will need to either use:
manager >> managerImport[i].gridSizeA >> managerImport[i].gridSizeB;
or read in as string and parse out of the string.

implementation counting sort

here is code for counting sorting
#include <iostream>
using namespace std;
int main(){
int a[]={2,3,1,2,3};
int n=sizeof(int)/sizeof(int);
int max=a[0];
for (int i=1;i<n;i++) {
if (a[i]>max) {
max=a[i];
}
}
int *output=new int[n];
for (int i=0;i<n;i++) {
output[i]=0;
}
int *temp=new int[max+1];
for (int i=0;i<max+1;i++) {
temp[i]=0;
}
for (int i=0;i<n;i++){
temp[a[i]]=temp[a[i]]+1;
}
for (int i=1;i<max+1;i++) {
temp[i]=temp[i]+temp[i-1];
}
for (int i=n-1;i>=0;i--) {
output[temp[a[i]]-1]=a[i];
temp[a[i]]=temp[a[i]]-1;
}
for (int i=0;i<n;i++) {
cout<<output[i]<<" ";
}
return 0;
}
but output is just 2,only one number. what is wrong i can't understand please guys help me
int n=sizeof(int)/sizeof(int);
is wrong. That just assigns 1 to n.
You mean
int n=sizeof(a)/sizeof(int);
I've not looked beyond this. No doubt there are more problems, but this is the most significant.
This is the kind of thing you can work out very easily with a debugger.
Look at this expression:
int n=sizeof(int)/sizeof(int);
What do you think the value of n is after this? (1)
Is that the appropriate value? (no, the value should be 5)
Does that explain the output you are seeing? (yes, that explains why only one number is shown)
My advice would be that if you're going to do this in C++, you actually try to use what's available in C++ to do it. I'd look up std::max_element to find the largest element in the input, and use an std::vector instead of messing with dynamic allocation directly.
When you want the number of elements in an array in C++, you might consider a function template something like this:
template <class T, size_t N>
size_t num_elements(T const (&x)[N]) {
return N;
}
Instead of dumping everything into main, I'd also write the counting sort as a separate function (or, better, a function template, but I'll leave that alone for now).
// warning: Untested code:
void counting_sort(int *input, size_t num_elements) {
size_t max = *std::max_element(input, input+num_elements);
// allocate space for the counts.
// automatically initializes contents to 0
std::vector<size_t> counts(max+1);
// do the counting sort itself.
for (int i=0; i<num_elements; i++)
++counts[input[i]];
// write out the result.
for (int i=0; i<counts.size(); i++)
// also consider `std::fill_n` here.
for (int j=0; j<counts[i]; j++)
std::cout << i << "\t";
}
int main() {
int a[]={2,3,1,2,3};
counting_sort(a, num_elements(a));
return 0;
}

How to pass two dimensions array to a function and how to call it

I've tried many time to pass the array to a function then do some calculation such as getting the total of the columns, the problem is I don't know how to call the result form the function, usually I get errors.
this is just one code I'm trying to solve it from yesterday :
#include <iostream>
using namespace std;
//prototype
int get_total(int whatever[][2], int row);
int main ()
{
const int row=2;
const int col=3;
int marks[row][col];
// this is prompt the user to input the values
for (int i=0; i<row;i++)
{
for (int p=0; p<col; p++)
{
cin >> marks[i][p];
}
cout << endl;
}
// this is just display what the user input as a table
for (int x=0; x< row ; x++)
{
for (int y=0; y<col ; y++)
{
cout << marks[x][y] << " ";
}
cout << endl;
}
int sum;
// this is the most important thing I want to know,
// how to call the function :(
sum=get_total(marks,row);
return 0;
}
// to get the total of each columns
const int row=3;
// not sure if the declaration is correct or not :(
int get_total(int whatever[][2], int row)
{
for (int i=0; i < 2; i++)
{
for (int p=0; p < 3; p++)
int total=0;
//this line is completly wrong, How can I calculate the total of columns?
total+=get_total[2][p];
}
// do we write return total ?
// I'm not sure because we need the total for each column
return total;
}
sorry for the mess, and I appreciate any help to explain passing the multidimensions arry to a function as parameter and how to call the function>
Arrays decay to pointers when calling functions.
You can do 2 things:
Pass the number of lines and columns as arguments to the function.
Use std::vector instead. I suggest you take a look at it, it'll do the trick and you'll learn something new and very useful.
Also, your function should do this:
int get_total(int** whatever)
{
//total is 0 at the beginning
int total=0;
for (int i=0; i < 2; i++)
{
for (int p=0; p < 3; p++)
//go through each element and add it to the total
total+=whatever[i][p];
}
return total;
}
This will return the total for the whole matrix, I'm assuming that's what you mean by getting the total of the columns
int marks[row][col]
This means that marks has type int[2][3].
int get_total(int whatever[][2], int row);
You've however declared get_total to accept an int(*)[2]. int[2][3] can decay to int(*)[3] but that is not compatible with int(*)[2], hence why you can't pass marks to get_total. You can instead declare get_total to accept an int(*)[3]:
int get_total(int whatever[][3], int row);
// equivalent to:
int get_total(int (*whatever)[3], int row);
If you instead decide to declare get_total to accept an int** or an int*, then you can't legally pass marks to it in the former case, and you can't legally iterate over the whole multidimensional array in the latter. Consider not using arrays, it's simpler this way.

How do I pass multi-dimensional arrays of unknown size into a function using pointers in c++?

Like the question says, I am trying to pass multi-dimensional arrays into a function to print it to a file for an engineering project. The format for which the data is inputted CANNOT be changed, so please don't suggest I just input it as a different datatype.
This particular function anticipates a two-dimensional array (although I have others with three dimensions after this one), where nothing is known about the size of the array until run-time. I know I must use pointers to point to each row of the array separately, but I have NO idea what the syntax is for passing it to the function. In the following code, the array in question is 'block'. The main function is just a little testing example I made to try to make it work:
#include<fstream>
using namespace std;
void of_write_blocks(string filename, string block_type[], int **block,
int grid[][3], string grade_type[], int grade[][3], int n_blocks, int m[])
{
ofstream file_out(filename.c_str(),ios::app);
file_out<<"\nblocks\n(\n";
for(int i=0;i<n_blocks;++i) {
file_out<<" "<<block_type[i]<<" ( ";
for(int j=0;j<m[i];++j)
file_out<<block[i][j]<<" ";
file_out<<") ( ";
file_out<<grid[i][0]<<' '<<grid[i][1]<<' '<<grid[i][2]<<" ) ";
file_out<<grade_type[i]<<" ( ";
file_out<<grade[i][0]<<' '<<grade[i][1]<<' '<<grade[i][2]<<" )\n";
}
file_out<<");\n";
}
//testing example:
int main()
{
int block[6][9];
for(int i=0; i<6;++i)
for(int j=0; i<9;++j)
block[i][j] = i*j;
int grid[6][3];
for(int i=0; i<6;++i)
for(int j=0; i<3;++j)
block[i][j] = i*j;
int grade[6][3];
for(int i=0; i<6;++i)
for(int j=0; i<3;++j)
block[i][j] = i*j;
string grade_type[6] = {"simpleGrading"};
string block_type[6] = {"hex"};
int m[6] = {8};
int n_blocks = 6;
of_write_blocks("name",block_type,block,grid,grade_type,grade,n_blocks,m);
}
any help is appreciated!
You can't. Multidimensional arrays are syntactic sugar, and are compiled directly into the code that does manipulations on the array, which is a single memory block. The dimensions are not passed into the function as parameters or anything like that as part of the array, as things are done in e.g. Java or C#.
If you need the dimensions of the array in your function, you'll need to just accept a pointer to the first element of the array, and the dimensions, and do the multiplies and adds to get the right index yourself.
Alternately, use something like a std::vector<std::vector<block>>, which pass the dimensions as part of the object, rather than a built in array.
If you have Boost installed, check out Boost Multi-Array.
For clarity I removed all the irrelevant code from your example.
#include <iostream>
#include <fstream>
using namespace std;
void of_write_blocks(int **block, int bh, int bw){
for(int i = 0; i < bh; ++i)
for(int j = 0; j < bw; ++j)
cout << block[i][j] << " ";
cout << endl;
}
int main(){
int bh, bw;
cin >> bh >> bw;
int** block;
block = new int*[bh];
for(int k = 0; k < bh; k++)
block[k] = new int[bw];
// initialize the array
for(int i = 0; i < bh; i++)
for(int j = 0; j < bw; j++)
block[i][j] = (i*bw) + j;
of_write_blocks( block, bh, bw);
}
In the main we are creating a 2D array and initializing it. Then we pass it to of_write_block, which prints the array. Is that what you wanted to do?
Why can't use a reference of array. See below example:
char c[10];
int i[10][20];
double d[10][20][30];
Write a wrapper function like this:
template<typename T, int SIZE>
void Array (T (&a)[SIZE])
{}
template<typename T, int SIZE1, int SIZE2>
void Array (T (&a)[SIZE1][SIZE2])
{}
template<typename T, int SIZE1, int SIZE2, int SIZE3>
void Array (T (&a)[SIZE1][SIZE2][SIZE3])
{}
This is just an example to demonstrate the syntax which will elegantly receive the array without any copying and also avoids confusing pointers. Also, if you are aware that you are going to use only for int then simply remove the typename and explicitly mention int. i.e.
template<int SIZE>
void Array (int (&a)[SIZE]); // explicitly mention int