I need to make a program that asks the user to input a number of strings, and then outputs the string database. The program should maintain a string database where each record is a string. The program keeps reading strings that the user has typed, and inserts the string at a sorted position in the database dynamically. The user presses ctrl+Z to end the process of inputting the strings, and then the program displays the whole string database.

The program only allows the user to input up to 10 strings, and if more are inputted an error message should be displayed.

Basically, the user types a number of sentences, and then the sentences are sorted (by the first letter of that sentence) and then outputted in that new order. So if someone typed:

Hello
How are you today
Are you okay?

the result would be:

Are you okay?
Hello
How are you today

The idea I have for my code is the following:

for the main function (pseudocode):

while (1){
read a string;
if not successful, end the while loop;
else insert the string at a sorted position in the string database;
}
display the string database;

so I am working on a function for the first 'if' statement, called readstring:

char *ReadString(char *a)
{
    for (char *b = a; *b; b++)

I believe this for loop scrolls through every character for a string, and I think what I need to do is have one pointer store the first character to one pointer, and then have that pointer store the next character as another pointer, and so on. I am really unclear as exactly how to approach this problem. If anyone can help me with this function/the rest of the problem that would be great, thanks!

#include <iostream>

using std::cin;
using std::cout;
using std::endl;

int main()
{
    cout << "                            String Database" << endl;
    cout << "         Please type some strings, and the database will sort them" << endl;
    cout << "                  Press ^Z to end the string input" << endl;

    while(1)
    {
        //read the string using ReadString function
        //If not successful, break;
        //else, insert the string at a sorted position in the database
    }
    //display the string database


}

//Functions

char *ReadString(char *a)
{
    for (char *b = a; *b; b++)

Recommended Answers

All 31 Replies

If you're going to use C++ I/O, you might as well use the std::string class rather than a char*. And for reading in a whole line of input at a time, use getline(). For the database itself, a vector would probably be appropriate. You could do something like this (pseudo c++ code):

#include <vector>
#include <iostream>
#include <string>

int main()
{
  using namespace std;
  vector<string> stringDatabase;
  string input;
  while(true)
  {
     getline(cin, input, '\n'); // I forget the exact parameter order
    /* find where the string goes */
    /* put the string in the vector */
  }
  /* output the contents of the vector
}

Not sure how to handle the Ctrl-Z off-hand though...

If you're going to use C++ I/O, you might as well use the std::string class rather than a char*. And for reading in a whole line of input at a time, use getline(). For the database itself, a vector would probably be appropriate. You could do something like this (pseudo c++ code):

#include <vector>
#include <iostream>
#include <string>

int main()
{
  using namespace std;
  vector<string> stringDatabase;
  string input;
  while(true)
  {
     getline(cin, input, '\n'); // I forget the exact parameter order
    /* find where the string goes */
    /* put the string in the vector */
  }
  /* output the contents of the vector
}

Not sure how to handle the Ctrl-Z off-hand though...

i should have clarified that I need to do this assignment using pointers and arrays, thanks!

an array of strings is a 2D array of type char. If the array is to hold up to 10 strings and each may be up to 256 char each, then you could declare it like this:

char arrayOfStrings[10][257];

You can use a loop with 2 conditionals to control the input:

int numberOfStrings starts at zero
bool enterAnotherString is true

while(numberOfStrings < 11 and enterAnotherString is true)
   enter string into arrayOfStrings
   increcement numberOfStrings
   ask user if they want to enter another string
     if input is no
        AnotherString is false

Once user input is ended sort the strings using standard string functions like strcmp() and your favorite sorting algorhithm. Since you will have at most 10 strings to sort, a bubble sort should be satisfactory and seems to be a favorite of programmers just starting their career. If you have to inplement your own function to compare strings, good luck. It's doable, it's a reasonable learning exercise, and it's a bit of a pain.

an array of strings is a 2D array of type char. If the array is to hold up to 10 strings and each may be up to 256 char each, then you could declare it like this:

char arrayOfStrings[10][257];

You can use a loop with 2 conditionals to control the input:

int numberOfStrings starts at zero
bool enterAnotherString is true

while(numberOfStrings < 11 and enterAnotherString is true)
   enter string into arrayOfStrings
   increcement numberOfStrings
   ask user if they want to enter another string
     if input is no
        AnotherString is false

Once user input is ended sort the strings using standard string functions like strcmp() and your favorite sorting algorhithm. Since you will have at most 10 strings to sort, a bubble sort should be satisfactory and seems to be a favorite of programmers just starting their career. If you have to inplement your own function to compare strings, good luck. It's doable, it's a reasonable learning exercise, and it's a bit of a pain.

to be safe I am going to make it 500 characters. I know that we are not supposed to ask the user to input more strings than 10, so I don't believe I need the boolean. basically the user can keep entering strings until he or she presses ctrl z (^z). any strings he or she enters more than 10 will just result in an error "No more strings!". so the program only has to record the first 10 strings it enters. i am unclear, however, how to implement this using ptrs. how do I get the user to keep inputting strings? is it just something like while numberstrings <11, cin.getline; numberstrings++;? but I would need a function after cin.getline that saves and stores the string to a new location to sort later, correct? so could the code be something like this:

int numberstrings == 0;
while (numberstrings<11)
{
cin.getline(string, 500)
store_string(char*string) // where store_string is the storage function;
numberstrings++;
}
//after while loop ends, I can create a function to display the sorted strings.

does this appear right? and if so, how can i go about creating this store_string function? and do I need a function later to sort the strings after they all have been entered? since the user can quit entering strings early, should this be an 'if' statement instead? thanks!

Lerner: A couple problems with the code you posted:

>> 1. int numberstrings == 0;

you need to use the assignment operator = instead of boolean operator ==.:mrgreen:

>>5. store_string(char*string)
This is a function prototype, not a function call

also i think that the vector container has a sort function of his own, so you could you this to sort the strings!

also i think that the vector container has a sort function of his own, so you could you this to sort the strings!

The sort function is a function of STL, nor vector. Here is an example of how to vector of sort c++ classes

so i want to continue from the code i was thinking of up above, where there is a while loop for numberstrings<11. then i have a function which stores the string to a separate database each time. what would be a correct way to write this function?

I was thinking something where:

char *ReadString(char *a)
{
for (char *b = a; *b; b++)

so it reads through every character in the string first, then can I do something like:

c* = b, underneith the for loop? I want something so that it stores the whole string to another location for each string, so i can sort it later. so say i wanted string one to go to location: 00FFFF0000 or something, then it stores string 2 to location 00FFFF00001, so that i can sort all these locations later. does this make sense? will something like c*=b store the entire string? or will it just keep replacing c with each letter in that string. do i need to make a string as a pointer? like string1* = b? this is due tomorrow, any help i can get would be great! thanks!

Here's some pseudocode for two ways I might do it:

int main()
{
  char* stringDB[10] = {0};

  // method 1: add in order
  while(/* condition to keep inputting */)
  {
    read in a line
    find where the line goes
    put the line in the correct spot, adjusting others as necessary
  }

  // method 2
  for(int i = 0; i < 10 && /* condition */; ++i)
  {
    input string and add it as stringDB[i];
  }
  sort stringDB;

  // then output
  for(int i = 0; i < 10; ++i)
    std::cout << stringDB[i] << "\n";
}

When you sort the char* array, you can use strcmp (from <cstring>) to compare them.

Here's some pseudocode for two ways I might do it:

int main()
{
  char* stringDB[10] = {0};

  // method 1: add in order
  while(/* condition to keep inputting */)
  {
    read in a line
    find where the line goes
    put the line in the correct spot, adjusting others as necessary
  }

  // method 2
  for(int i = 0; i < 10 && /* condition */; ++i)
  {
    input string and add it as stringDB[i];
  }
  sort stringDB;

  // then output
  for(int i = 0; i < 10; ++i)
    std::cout << stringDB[i] << "\n";
}

When you sort the char* array, you can use strcmp (from <cstring>) to compare them.

i want to go with method 2. So I tried the following code with my Visual C++, but it gave me an error about a null pointer and the program wouldn't run. Right now I just want to worry about getting the main part of my function to work, without sorting the strings for now. Once I get my program to work with storing the strings I can worry about creating a function to sort them. so this is my code thus far:

#include <iostream>

using std::cin;
using std::cout;
using std::endl;

int main()
{
    cout << "                            String Database" << endl;
    cout << "         Please type some strings, and the database will sort them" << endl;
    cout << "                  Press ^Z to end the string input" << endl;

    char* string[10] = {0};

    for (int i = 0; i <= 10; ++i)
    {
        cin.getline(string[i], 500);
    }

    //Function to sort the string

    for(int i = 0; i <= 10; ++i)
    {
    cout << string[i] << "\n";
    }
    
    


}

Can anyone see why it gives me a null pointer error? thanks!

There's two bugs I see here. One's my fault, the other isn't ;)

The first is that the array values are set to 0, which is null memory. They need to be given different values so that they point to memory you can write to. There's two ways to do this:
- Initialize them all at the beginning:

char* string[10];
for(int i = 0; i < 10; ++i)
  string[i] = new char[500];
// ... rest of the program
for(int i = 0; i < 10; ++i)
  delete string[i]; // free the memory
return 0; // end of main

- allocate them as you need them:

char* string[10] = {0};
// loop to read things in:
for(int i = 0; i < 10; ++i)
{
  char* temp = new char[500];
  cin.getline(temp, 500);
  string[i] = temp; // makes the pointer point to the newly allocated space
  // also need to delete at the end of the end of the program
}

The benefit of the second is that if the user only inputs 3 strings, you only allocate memory 3 times.

The second bug is that you have <= in the for loop conditions, when it should just be <. Easy fix ;)

thanks! i went with the second method and it worked fine. I think i can figure out how to execute the program early when the user types ^z, but i need help with sorting the database after its been stored. the program needs to sorts the strings in ascending order according to the first letter of each string. so do I need to create a function that points to the first letter of each string? and then sorts it? and is there already a preexisting function that will take my string database and sort it in ascending order for me already? thanks! below is my code thus far:

#include <iostream>

using std::cin;
using std::cout;
using std::endl;

int main()
{
    cout << "                            String Database" << endl;
    cout << "         Please type some strings, and the database will sort them" << endl;
    cout << "                  Press ^Z to end the string input" << endl;

    char* string[10] = {0};

    for (int i = 0; i < 10; ++i)
    {
        char* temp = new char[500];
        cin.getline(temp, 500);
        string[i] = temp;
    }

    //Function to sort the string

    for(int i = 0; i <= 10; ++i)
    {
    cout << string[i] << "\n";
    }
    
    


}

//Functions

Your last for loop is off by one -- running from 0 to 10 where it should have gone from 0 to 9.

As far as sorting is concerned, something like this might be worth reading to see if it serves your purpose....

Member Avatar for iamthwee

You shouldn't be using string as a variable name.

And don't forget to use delete[] if you're using new .

You shouldn't be using string as a variable name.

And don't forget to use delete[] if you're using new .

Right now I am having a problem with the sort part of my code at this point:

while(temp>=string[k])

The program is not recognizing this comparison correctly. below is my current code:

#include <iostream>

using std::cin;
using std::cout;
using std::endl;



int main()
{
    cout << "                            String Database" << endl;
    cout << "         Please type some strings, and the database will sort them" << endl;
    cout << "                  Press ^Z to end the string input" << endl;

    char* string[10] = {0};
    for(int b=0;b<10;b++)
        string[b]="zzzzzz";
    
    

    for (int i = 0; i < 10; i++)
    {    
        char* temp = new char;//[500];
        cin.getline(temp, 500);
        if(i==0)
        {    string[i] = temp; // makes the pointer point to the newly allocated space
        }
        else
        {    int k=0;
            while(temp>=string[k])
            {    cout<<temp<<">="<<string[k]<<"?"<<endl;
                k++;
            }
            cout<<k<<endl;

            int p;
            for(p=9;p>k;p--)
            {    string[p]=string[p-1];
            }
            string[p]=temp;
        }
    }

    for(int i = 0; i < 10; ++i)
    {  cout << string[i] << "\n";
    }
    
    return 0;


}

Right now the program outputs whether each character you type is greater than the other. but if you type 'd' on one line, and then 'b' the next, it says 'b' is > 'd'. can anyone help me debug this? thanks!

Member Avatar for iamthwee

That's because you're confusing c++ and c.

That's because you're confusing c++ and c.

I just switched my code around to use strcmp and now it works fine! I now need help implementing a function that executes the program early if i type ^Z or ^z. if the user wants to sort the strings early they input this command. So I was thinking of making a boolean function that returns false if they input this, but i want to make sure that the ^Z is not included in the database when it sorts. this is what i have for my code thus far but I am having problems with it:

#include <iostream>

using std::cin;
using std::cout;
using std::endl;

bool z();

int main()
{
    cout << "                            String Database" << endl;
    cout << "         Please type some strings, and the database will sort them" << endl;
    cout << "                  Press ^Z to end the string input" << endl;

    char* string[10] = {0};
    for(int b=0;b<10;b++)
        string[b]="zzzzzz";
    
    

    for (int i = 0; i < 10 && z(); i++)
    {    
        char* temp = new char;//[500];
        cin.getline(temp, 500);
        if(i==0)
        {    string[i] = temp; // makes the pointer point to the newly allocated space
        }
        else
        {    int k=0;
            while(strcmp(temp,string[k])>=0)
            {    
                k++;
            }
            

            int p;
            for(p=9;p>k;p--)
            {    string[p]=string[p-1];
            }
            string[p]=temp;
        }
    }

    for(int i = 0; i < 10; ++i)
    {  cout << string[i] << "\n";
    }
    
    return 0;


}

//Functions

bool z()
{ char* a[10]={0};
    cin.getline(blah);
    if(a=="^z" || a=="^Z")
        return false;
    return true;
}

it gives me conversion errors. does anyone know if I can use a boolean function like this to accomplish what I need to get done? do I need to do something else to make sure that ^Z wont be included in the database after it sorts? thanks!

Member Avatar for iamthwee

does that mean I can't do the comparison that way? i need to do this using c++

No, you can do the comparison using char * instead of std::strings. But you would have to use strcmp instead. And you would have to include the header file #include <cstring> .


I believe this was mentioned before.

Unfortunately, because c++ accepts both c and c++ syntax it is very easy for newbies, like yourself to try and use the two variants of c and c++ as one language.

Of course there is nothing wrong with that if you know what you're doing. You don't.

Therefore I would advise you to use either one or the other. c or c++, unless of course your teacher wants you to use char* with c++.

No, you can do the comparison using char * instead of std::strings. But you would have to use strcmp instead. And you would have to include the header file #include <cstring> .


I believe this was mentioned before.

Unfortunately, because c++ accepts both c and c++ syntax it is very easy for newbies, like yourself to try and use the two variants of c and c++ as one language.

Of course there is nothing wrong with that if you know what you're doing. You don't.

Therefore I would advise you to use either one or the other. c or c++, unless of course your teacher wants you to use char* with c++.

That's because you're confusing c++ and c.

I just switched my code around to use strcmp and now it works fine! I now need help implementing a function that executes the program early if i type ^Z or ^z. if the user wants to sort the strings early they input this command. So I was thinking of making a boolean function that returns false if they input this, but i want to make sure that the ^Z is not included in the database when it sorts. this is what i have for my code thus far but I am having problems with it:

#include <iostream>

using std::cin;
using std::cout;
using std::endl;

bool z();

int main()
{
    cout << "                            String Database" << endl;
    cout << "         Please type some strings, and the database will sort them" << endl;
    cout << "                  Press ^Z to end the string input" << endl;

    char* string[10] = {0};
    for(int b=0;b<10;b++)
        string[b]="zzzzzz";
    
    

    for (int i = 0; i < 10 && z(); i++)
    {    
        char* temp = new char;//[500];
        cin.getline(temp, 500);
        if(i==0)
        {    string[i] = temp; // makes the pointer point to the newly allocated space
        }
        else
        {    int k=0;
            while(strcmp(temp,string[k])>=0)
            {    
                k++;
            }
            

            int p;
            for(p=9;p>k;p--)
            {    string[p]=string[p-1];
            }
            string[p]=temp;
        }
    }

    for(int i = 0; i < 10; ++i)
    {  cout << string[i] << "\n";
    }
    
    return 0;


}

//Functions

bool z()
{ char* a[10]={0};
    cin.getline(a);
    if(a=="^z" || a=="^Z")
        return false;
    return true;
}

it gives me conversion errors. does anyone know if I can use a boolean function like this to accomplish what I need to get done? do I need to do something else to make sure that ^Z wont be included in the database after it sorts? thanks!

//Functions

bool z()
{ 
    char* a[10]={0};
    cin.getline(blah);
    if(a=="^z" || a=="^Z")
        return false;
    return true;
}

I get several errors on the above code.

Compiling...
test1.cpp
C:\dvlp\test1\test1.cpp(63) : error C2065: 'blah' : undeclared identifier
C:\dvlp\test1\test1.cpp(64) : error C2446: '==' : no conversion from 'char *' to 'char ** '
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
C:\dvlp\test1\test1.cpp(64) : error C2040: '==' : 'char *[10]' differs in levels of indirection from 'char [3]'
C:\dvlp\test1\test1.cpp(64) : error C2446: '==' : no conversion from 'char *' to 'char ** '
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
C:\dvlp\test1\test1.cpp(64) : error C2040: '==' : 'char *[10]' differs in levels of indirection from 'char [3]'
Error executing cl.exe.

test1.exe - 5 error(s), 0 warning(s)

Member Avatar for iamthwee

You don't need the bool function.

Instead you need to do an actual comparison in the for loop.

cin.getline(temp, 500);

For example if temp is equal to "^Z" then bail out. Again you would be using string compare I assume.

Remember to use delete[] as well.

>> if(a=="^z" || a=="^Z")
you can't do string comparisons that way. You have to use C's strcmp() function

if(strcmp(a"^z") == 0 || strcmp(a,"^Z") == 0)

And the problem with the above code is that ^Z does not appear in the strings, and if they did it would not be as two ascii characters '^' and 'Z'. If you look at an ascii chart you will see that Ctrl+Z has a decimal value of 26 (the 26th letter in the alphabet).

>> if(a=="^z" || a=="^Z")
you can't do string comparisons that way. You have to use C's strcmp() function

if(strcmp(a"^z") == 0 || strcmp(a,"^Z") == 0)

And the problem with the above code is that ^Z does not appear in the strings, and if they did it would not be as two ascii characters '^' and 'Z'. If you look at an ascii chart you will see that Ctrl+Z has a decimal value of 26 (the 26th letter in the alphabet).

I was also thinking about using the cin.eof() function because it seems a lot easier than a boolean. i believe when ctrl+z is entered, it recognizes it as the end of the file and should run the program. I know that it should look something like this:

if(cin.eof())
{
cout << "done!"
exit(0);
}

but I am not sure where I need to implement this in my program. Also, can you please explain the 'delete[]' thing to me? I know it has been brought up numerous times but I am not sure what it does or how to use it, so I have no implemented it yet. thanks!

Also, this piece of code has a BIG problem:

for (int i = 0; i < 10 && z(); i++)
    {    
        char* temp = new char;//[500];
        cin.getline(temp, 500);

How large is the area pointed to by temp? I'm surprised it didn't crash on you yet.

I was also thinking about using the cin.eof() function because it seems a lot easier than a boolean. i believe when ctrl+z is entered, it recognizes it as the end of the file and should run the program. I know that it should look something like this:

if(cin.eof())
{
cout << "done!"
exit(0);
}

but I am not sure where I need to implement this in my program.

Maybe where you ask for the input?

>> Press ^Z to end the string input

This is problematic. First, it isn't ^Z that the user would enter, it's Ctrl-Z, which appears as ^Z on a console screen if you have a DOS/windows machine. Second, using Ctrl-Z is the DOS/windows specific way for manually entering an EOF marker and is not portable (for example I think it's Ctrl-D in Unix). Third, the user doesn't have to enter Ctrl-z to terminate entery into any given string, a newline char will do just as well, in fact it's the default delimiting char for getline(). Fourth, when I tried it, using Ctrl-z to terminate input into the array, is not at all straightforward. If you can terminate input into the array by using some other approach, that is, if using Ctrl-z isn't an instructor/employer imposed requirement, then I would encourage you to do so.

If you can terminate input into the array by using some other approach, that is, if using Ctrl-z isn't an instructor/employer imposed requirement, then I would encourage you to do so.

Yeah, I was going to mention that, too, but forgot. Simply read your line and if there is only a newline in the buffer, assume they didn't want to input anything and start processing...

Yeah, I was going to mention that, too, but forgot. Simply read your line and if there is only a newline in the buffer, assume they didn't want to input anything and start processing...

no, using the ctrl+z is an instructor requirement for the problem. basically I was told that after each time the user enters a line, it needs to check for the cin.eof() condition and handle it appropriately. Below is my full code and where I tried implementing it, but instead it just ends the code completely where i type it in, and doesnt show the output. maybe I am just putting it in the wrong spot?

#include <iostream>

using std::cin;
using std::cout;
using std::endl;



int main()
{
    cout << "                            String Database" << endl;
    cout << "         Please type some strings, and the database will sort them" << endl;
    cout << "                  Press ^Z to end the string input" << endl;

    char* string[10] = {0};
    for(int b=0;b<10;b++)
        string[b]="zzzzzz";
    
    

    for (int i = 0; i < 10; i++)
    {    
        char* temp = new char;//[500];
        cin.getline(temp, 500);
        
        if(i==0)
        {    string[i] = temp; // makes the pointer point to the newly allocated space
        }

        else if (cin.eof())
        {
            cout << "done!";
            exit(0);
        }

        else
        {    int k=0;
            while(strcmp(temp,string[k])>=0)
            {    
                k++;
            }
            

            int p;
            for(p=9;p>k;p--)
            {    string[p]=string[p-1];
            }
            string[p]=temp;
        }
    }

    for(int i = 0; i < 10; ++i)
    {  cout << string[i] << "\n";
    }
    
    return 0;


}

>>basically I was told that after each time the user enters a line, it needs to check for the cin.eof() condition and handle it appropriately.

getline() will terminate input into the indicated char buffer if the specified number of char is found, if the terminating char is found, or if the end of file indicator is found. These terminating conditions are automatic. That means you don't have to check for end of file manually, getline() will do it for you. I recommend you do something like this:

char arrayOfStrings[10][80];
int i = 0;
char ch;
bool AddMore = true;

while(AddMore)
{
    if(i < 10)
      cin.getline(arrayOfStrings[i++]);
    else
      cout << "do not enter any more strings" << endl;
    
    cout << "to stop now enter y";
    cin >> y;
    if(ch == 'y')
      AddMore = false;
}

>>basically I was told that after each time the user enters a line, it needs to check for the cin.eof() condition and handle it appropriately.

getline() will terminate input into the indicated char buffer if the specified number of char is found, if the terminating char is found, or if the end of file indicator is found. These terminating conditions are automatic. That means you don't have to check for end of file manually, getline() will do it for you. I recommend you do something like this:

char arrayOfStrings[10][80];
int i = 0;
char ch;
bool AddMore = true;

while(AddMore)
{
    if(i < 10)
      cin.getline(arrayOfStrings[i++]);
    else
      cout << "do not enter any more strings" << endl;
    
    cout << "to stop now enter y";
    cin >> y;
    if(ch == 'y')
      AddMore = false;
}

I tried putting the cin.eof() into the original 'if' statement but my code crashes. I am not sure if it is because of the cin.eof() condition i added or because I havent impleemented the delete[] thing yet. can someone please explain where I should add delete[] to my code? thanks!

#include <iostream>

using std::cin;
using std::cout;
using std::endl;



int main()
{
    cout << "                            String Database" << endl;
    cout << "         Please type some strings, and the database will sort them" << endl;
    cout << "                  Press ^Z to end the string input" << endl;

    char* string[10] = {0};
    for(int b=0;b<10;b++)
        string[b]="zzzzzz";
    
    

    for (int i = 0; i < 10 || cin.eof(); i++)
    {    
        char* temp = new char;//[500];
        cin.getline(temp, 500);
        
            if(i==0)
            {    string[i] = temp; // makes the pointer point to the newly allocated space
            }

            else
            {    int k=0;
                while(strcmp(temp,string[k])>=0)
                {    
                    k++;
                }
            

                int p;
                for(p=9;p>k;p--)
                {    string[p]=string[p-1];
                }
                string[p]=temp;
            }
        //}
    }

    for(int i = 0; i < 10; ++i)
    {  cout << string[i] << "\n";
    }
    
    return 0;


}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.