I am trying to use pointer in reading string array,but it occurs an exception.
Here is the code:
#include<vector>
#include<string>
#include<iostream>
using namespace std;
int countn = 1;
class Solution {
public:
string findPrefix(string compa, string& compb,int n) {
string prefixi;
for (int i = 0; i < compa.length(); i++) {
if (compa[i] == compb[i]) {//Exception occurs here
prefixi.push_back(compa[i]);
}
else break;
}
countn++;
string* nxt = &compb;
nxt++;
if (countn<=n) {
prefixi = findPrefix(prefixi,*nxt,n);
}
return prefixi;
}
string longestCommonPrefix(vector<string>& strs) {
int n = strs.size();
string prefix;
prefix = findPrefix(strs[0], strs[countn],n);
return prefix;
}
};
int main() {
vector<string> str = { "flower", "fly","flip"};
Solution test;
string ans = test.longestCommonPrefix(str);
cout << ans << endl;
}
Exception occurs in line13
Then I checked the auto box and to find that the pointer nxt is pointing to the last string in str vector(string"filp"), I wonder if the pointer is out of boundary, but I do not know how to fix it and make my code work. Help me plz.
Related
I am writing a C++ program for homework, and it needs to count the characters in a char arr[n] string. However, my counter keeps returning the wrong values. I have looked through other answers to similar questions, however, they are not specific to C++ and none of the answers explain the value I am getting.
#include<iostream>
using namespace std;
#include<string.h>
#include <stdlib.h>
class Counter
{
public:
char word[20];
int totChar{ 0 };
void setWord(char word)
{
this->word[20] = word;
}
void setCount(int totChar)
{
this->totChar = totChar;
}
int getLength()
{
return totChar;
}
void charCount()
{
int n = 0;
for (int i = 0; word[i] != '\0'; i++) {
if (word[i] != '\0')
{
n++;
}
}
setCount(n);
}
};
int main()
{
char text[20];
cout << "Enter the string:" << endl;
cin >> text;
Logic input;
input.setWord(text[20]);
input.charCount();
// input.resetWord();
cout << input.getLength();
}
So it seems you haven't figured out how arrays and C strings work in C++ yet.
void setWord(const char* word)
{
strcpy(this->word, word);
}
and
Logic input;
input.setWord(text);
Your code is a bit weird, I guess you are just experimenting, but I think those two changes should make it work.
im currently setting up the highscore-part for a game and I have a very weird problem because of the weird behaviour of the std::sort function.
Im doing the whole thing in RAD Studio 10.2 (Embarcadero IDE) in C++.
So he is my code:
std::string Line;
int count = 0;
int i = 0;
ifstream File("Highscore.txt");
if(File.is_open())
{
while(getline(File, Line))
{
count += 1;
}
File.close();
}
ifstream ReadFile("Highscore.txt");
if(ReadFile.is_open())
{
string *scores = NULL;
scores = new string[count];
while(getline(ReadFile, Line))
{
scores[i] = Line;
i += 1;
}
ReadFile.close();
std::sort(scores, (scores+count));
UnicodeString Uscores1 = scores[0].c_str();
UnicodeString Uscores2 = scores[1].c_str();
UnicodeString Uscores3 = scores[2].c_str();
UnicodeString Uscores4 = scores[3].c_str();
UnicodeString Uscores5 = scores[4].c_str();
LScore1->Caption = Uscores1;
LScore2->Caption = Uscores2;
LScore3->Caption = Uscores3;
LScore4->Caption = Uscores4;
LScore5->Caption = Uscores5;
}
I get no errors from the compiler/linker and everything work should fine.
The string array gets filled correctly and so on.
But its not sorting.
To show the problem to you I made a screenshot - on the left you can see the txtfile with the scores; on the right you can see the output after the sorting algorithm:
My question now is why this is happening?
Thanks for you help
Welcome to C++. Since you want to list numbers by rank, read them as int not string. Forget about operator new. You will not need it for years, if ever. Use standard containers like std::vector, which take care of the memory allocation and de-allocation transparently.
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
int main() {
using namespace std;
vector<int> scores;
{
ifstream inp("Highscore.txt");
int next;
while (inp >> next) {
scores.push_back(next);
}
}
sort(scores.begin(), scores.end());
for (auto s : scores) {
cout << s << '\n';
}
return 0;
}
How about something like:
int i = 0;
int * scoresInteger = NULL;
scoresInteger = new int[count];
for(i = 0; i < count; i++)
{
scoresInteger[i] = std::stoi(scores[i]);
}
std::sort(scoresInteger, scoresInteger + count);
If you need to, you can convert the integers back into strings using targetStrings[i] = std::to_string(scoresInteger[i]).
string * targetScores = NULL;
targetScores = new std::string[count];
for(i = 0; i < count; i++)
{
targetScores[i] = std::to_string(scoresInteger[i]);
}
delete [] scoresInteger;
scoresInteger = NULL;
Don't forget to delete [] targetScores later.
My question now is why this is happening?
Because your scores are compared as strings and not as ints. Because of that "3" is greater that "25"
std::cout << std::boolalpha << (std::string("3") > std::string("25")) << std::endl; // true
Luckily you can pass a custom comparator (or lambda) to the std::sort to make it behave just as you want:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
const int count = 5;
std::string scores[count] = { "35","25","3","4","5" };
// TWEAKED SORT
std::sort(scores, scores + count, [](std::string const &s1, std::string const &s2)
{
return std::stoi(s2) < std::stoi(s1);
});
// TEST
for (auto const &s : scores)
{
std::cout << s << std::endl;
}
}
The compared strings in the above example are converted to ints and then compared, resulting in the desired sorting order.
35
25
5
4
3
Please note that I do not agree with the rest of your code and I think you should rethink the implementation, as it would be much easier, safer and more efficient to use std::vector<std::string> for your task.
The code was written in VS community 2013. The program worked fine in debugger mode. But crashed while execution. Please let me know what could be the problem.
sample test case:
10
aaa
bbb
ccc
aaa
The program crashed at 3rd input line, sometimes at 4th input line.
#include<iostream>
#include<string.h>
#include<string>
using namespace std;
class registeration
{
public:
char* name;
int count;
registeration *next;
registeration()
{
name = new char(20);
count = 0;
next = NULL;
}
};
int main()
{
int n;
cin >> n;
char* str = new char(n);
registeration *regStart = new registeration();
while (n--)
{
cin >> str;
if (regStart->next == NULL)
{
registeration *reg = new registeration();
regStart->next = reg;
reg->count++;
//strcpy(reg->name, str);
strcpy_s(reg->name, 20, str);
}
else
{
registeration *reg = new registeration();
reg = regStart->next;
while (reg->next != NULL && strcmp(str, reg->name))
{
//registeration *reg1 = new registeration();
reg = reg->next;
}
if (!strcmp(str, reg->name))
reg->count++;
else
{
registeration *reg1 = new registeration();
strcpy_s(reg1->name, 20, str);
reg1->count++;
reg->next = reg1;
}
}
}
registeration *reg = new registeration();
reg = regStart->next;
while (reg != NULL)
{
if (reg->count > 1)
cout << reg->name << endl;
reg = reg->next;
}
return 0;
}
One obvious bug is in these lines:
name = new char(20);
char* str = new char(n);
They allocate a single character initialized to the given value. Instead you intend to allocate an array of characters, which you do as follows:
name = new char[20];
char* str = new char[n];
(With bracket instead of parentheses.)
It is better though to use the standard C++ utilities that manage the memory for you, like std::string for strings and std::vector or std::list for the containers.
EDIT: This code does the same thing as yours, better:
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
int n;
cin >> n;
map<string, int> m;
for(int i = 0; i < n; ++i)
{
string s;
cin >> s;
m[s]++;
}
for(const auto &pr : m)
if(pr.second > 1)
cout << pr.first << '\n';
}
I'm a C# programmer that recently wanted to delve into something lower level so last week started learning C++ but have stumbled on something I thought would be fairly simple.
I enter the following string into my program:
"this is a test this test" and would expect the wordStructList to contain a list of 4 words, with occurrences of "test" and "this" set to 2. When debugging however, the string comparison (I've tried .compare and ==) always seems to increasing the value of occurrences no matter whether the comparison is true.
e.g. currentName = "is"
word = "this"
but occurrences is still been incremented.
#include "stdafx.h"
using std::string;
using std::vector;
using std::find;
using std::distance;
struct Word
{
string name;
int occurrences;
};
struct find_word : std::unary_function<Word, bool>
{
string name;
find_word(string name):name(name) { }
bool operator()(Word const& w) const
{
return w.name == name;
}
};
Word GetWordStruct(string name)
{
Word word;
word.name = name;
word.occurrences = 1;
return word;
}
int main(int argc, char argv[])
{
string s;
string delimiter = " ";
vector<string> wordStringList;
getline(std::cin, s);
do
{
wordStringList.push_back(s.substr(0, s.find(delimiter)));
s.erase(0, s.find(delimiter) + delimiter.length());
if (s.find(delimiter) == -1)
{
wordStringList.push_back(s);
s = "";
}
} while (s != "");
vector<Word> wordStructList;
for (int i = 0; i < wordStringList.size(); i++)
{
Word newWord;
vector<Word>::iterator it = find_if(wordStructList.begin(), wordStructList.end(), find_word(wordStringList[i]));
if (it == wordStructList.end())
wordStructList.push_back(GetWordStruct(wordStringList[i]));
else
{
string word(wordStringList[i]);
for (vector<Word>::size_type j = 0; j != wordStructList.size(); ++j)
{
string currentName = wordStructList[j].name;
if(currentName.compare(word) == 0);
wordStructList[j].occurrences++;
}
}
}
return 0;
}
I hope the question makes sense. Anyone shed any light on this? I'm also open to any tips about how to make the code more sensible/readable. Thanks
The problem is the semicolon after this if statement:
if(currentName.compare(word) == 0);
The semicolon terminates the statement, so the next line
wordStructList[j].occurrences++;
is not part of the if statement any more and will always be executed.
Can someone help me with this: This is a program to find all the permutations of a string of any length. Need a non-recursive form of the same. ( a C language implementation is preferred)
using namespace std;
string swtch(string topermute, int x, int y)
{
string newstring = topermute;
newstring[x] = newstring[y];
newstring[y] = topermute[x]; //avoids temp variable
return newstring;
}
void permute(string topermute, int place)
{
if(place == topermute.length() - 1)
{
cout<<topermute<<endl;
}
for(int nextchar = place; nextchar < topermute.length(); nextchar++)
{
permute(swtch(topermute, place, nextchar),place+1);
}
}
int main(int argc, char* argv[])
{
if(argc!=2)
{
cout<<"Proper input is 'permute string'";
return 1;
}
permute(argv[1], 0);
return 0;
}
Another approach would be to allocate an array of n! char arrays and fill them in the same way that you would by hand.
If the string is "abcd", put all of the "a" chars in position 0 for the first n-1! arrays, in position 1 for the next n-1! arrays, etc. Then put all of the "b" chars in position 1 for the first n-2! arrays, etc, all of the "c" chars in position 2 for the first n-3! arrays, etc, and all of the "d" chars in position 3 for the first n-4! arrays, etc, using modulo n arithmetic in each case to move from position 3 to position 0 as you are filling out the arrays.
No swapping is necessary and you know early on if you have enough memory to store the results or not.
A stack based non-recursive equivalent of your code:
#include <iostream>
#include <string>
struct State
{
State (std::string topermute_, int place_, int nextchar_, State* next_ = 0)
: topermute (topermute_)
, place (place_)
, nextchar (nextchar_)
, next (next_)
{
}
std::string topermute;
int place;
int nextchar;
State* next;
};
std::string swtch (std::string topermute, int x, int y)
{
std::string newstring = topermute;
newstring[x] = newstring[y];
newstring[y] = topermute[x]; //avoids temp variable
return newstring;
}
void permute (std::string topermute, int place = 0)
{
// Linked list stack.
State* top = new State (topermute, place, place);
while (top != 0)
{
State* pop = top;
top = pop->next;
if (pop->place == pop->topermute.length () - 1)
{
std::cout << pop->topermute << std::endl;
}
for (int i = pop->place; i < pop->topermute.length (); ++i)
{
top = new State (swtch (pop->topermute, pop->place, i), pop->place + 1, i, top);
}
delete pop;
}
}
int main (int argc, char* argv[])
{
if (argc!=2)
{
std::cout<<"Proper input is 'permute string'";
return 1;
}
else
{
permute (argv[1]);
}
return 0;
}
I've tried to make it C-like and avoided c++ STL containers and member functions (used a constructor for simplicity though).
Note, the permutations are generated in reverse order to the original.
I should add that using a stack in this way is just simulating recursion.
First one advice - don't pass std:string arguments by value. Use const references
string swtch(const string& topermute, int x, int y)
void permute(const string & topermute, int place)
It will save you a lot of unnecessary copying.
As for C++ solution, you have functions std::next_permutation and std::prev_permutation in algorithm header. So you can write:
int main(int argc, char* argv[])
{
if(argc!=2)
{
cout<<"Proper input is 'permute string'" << endl;
return 1;
}
std::string copy = argv[1];
// program argument and lexically greater permutations
do
{
std::cout << copy << endl;
}
while (std::next_permutation(copy.begin(), copy.end());
// lexically smaller permutations of argument
std::string copy = argv[1];
while (std::prev_permutation(copy.begin(), copy.end())
{
std::cout << copy << endl;
}
return 0;
}
As for C solution, you have to change variables types from std::string to char * (ugh, and you have to manage memory properly). I think similar approach - writing functions
int next_permutation(char * begin, char * end);
int prev_permutation(char * begin, char * end);
with same semantics as STL functions - will do. You can find source code for std::next_permutation with explanation here. I hope you can manage to write a similar code that works on char * (BTW std::next_permutation can work with char * with no problems, but you wanted C solution) as I am to lazy to do it by myself :-)
Have you tried using the STL? There is an algorithm called next_permutation which given a range will return true on each subsequent call until all permutations have been encountered. Works not only on strings but on any "sequence" type.
http://www.sgi.com/tech/stl/next_permutation.html
This solves the problem without recursion. The only issue is that it will generate duplicate output in the case where a character is repeated in the string.
#include<iostream.h>
#include<conio.h>
#include<stdio.h>
#include<string.h>
int factorial(int n)
{
int fact=1;
for(int i=2;i<=n;i++)
fact*=i;
return fact;
}
char *str;
void swap(int i,int j)
{
char temp=str[i];
str[i]=str[j];
str[j]=temp;
}
void main()
{
clrscr();
int len,fact,count=1;
cout<<"Enter the string:";
gets(str);
len=strlen(str);
fact=factorial(len);
for(int i=0;i<fact;i++)
{
int j=i%(len-1);
swap(j,j+1);
cout<<"\n"<<count++<<". ";
for(int k=0;k<len;k++)
cout<<str[k];
}
getch();
}
#include <iostream>
#include <string>
using namespace std;
void permuteString(string& str, int i)
{
for (int j = 0; j < i; j++) {
swap(str[j], str[j+1]);
cout << str << endl;
}
}
int factorial(int n)
{
if (n != 1) return n*factorial(n-1);
}
int main()
{
string str;
cout << "Enter string: ";
cin >> str;
cout << str.length() << endl;
int fact = factorial(str.length());
int a = fact/((str.length()-1));
for (int i = 0; i < a; i++) {
permuteString(str, (str.length()-1));
}
}