I want an array of cstrings separated by white space - c++

I am trying to get user input and put it into an array of cstrings separated by a space. When I print the array to the screen though I get nothing. I am sure I am doing something stupid, but I have been stuck trying different ways for a while. Any help would be appreciated. Here is the code.
#include <iostream>
#include <cstring>
using namespace std;
void stuff(char command[][25], int length)
{
char ch;
for(int i = 0; i < length; i ++)
{
int b = 0;
cin.get(ch);
while(!isspace(ch))
{
command[i][b++] = ch;
cin.get(ch);
}
command[i][b] = '\0';
cout << endl;
}
}
int main()
{
char cha[10][25];
char ch;
int len = 0;
while(ch != '\n')
{
cin.get(ch);
if(isspace(ch))
{
len++;
}
}
stuff(cha,len);
for(int i = 0; i < len; i++)
{
cout << cha[i] << endl;
}
cout << len << endl;
return 0;
}

a) ch is undefined when you first test it with while (ch != '\n'). Initialize it to zero or something.
b) You don't write any values into cha in the while loop. Perhaps something like:
int pos = 0;
while(ch != '\n') {
cin.get(ch);
if (isspace((unsigned)ch)) {
if (pos > 0) {
++len;
pos = 0;
}
}
else {
cha[len][pos] = ch;
++pos;
}
}
c) You are reading the stream again in stuff(...) but have already consumed what you wanted to get from the stream in main().
d) This code suffers from a number of buffer overrun and stack corruption opportunities. perhaps use a std::vector<std::string> instead. If it runs out of memory it will throw an exception rather than make a mess on the stack.
Perhaps something like this (untested):
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void main()
{
typedef std::vector<std::string> strvec;
strvec cha;
std::string s;
char ch = 0;
while(ch != '\n') {
cin.get(ch);
if (isspace((unsigned)ch)) {
if (!s.empty()) {
cha.push_back(s);
s.clear();
}
}
else {
s.push_back(ch);
}
}
// don't need to call 'stuff' to null terminate.
for (strvec::iterator i = cha.begin(); i != cha.end(); ++i) {
cout << *i << endl;
}
cout << cha.size() << endl;
}
This could be a little more efficient than it is but hopefully it is easy to understand.

You are reading the whole input in the while cycle in the main to read length(number of strings), but you never store it. Later on in stuff cin.get will read nothing. Maybe store the input in cha during the first cycle?

Related

Jump to a specific vector place if a condition is met and start reading it from there

We need to create a universal Turing machine.
We have a file with the provided information: tape count, starting input, starting position and the rules.
Reading from the file isn't that big of a problem. What I'm doing right now is creating a structure vector and reading all the rules to there.
What I can't figure out is how to make the machine itself work. We know that the starting state is always zero, so I'm starting from there. Looking for the rules that start with this state, but what I cannot figure out is what if I have to jump back to the first rules? What to do then? What can of counting mechanism for the vector can I implement? I'm really new to vectors. I'll add that for the algorithm itself.
No more than two loops can be used, not counting printing out text or reading from the file.
The code I have right now is:
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <Windows.h>
struct rule {
std::string qstate; // dabartine busena
char csymbol; // dabartinis simbolis
char nsymbol; // naujasis simbolis
char direction; // i kuria puse eis galvute
std::string nstate; // naujoji busena
};
void printingText(std::vector<char> input, int position, long long steps);
void searchingForASymbolOrState(std::vector<rule> rules, std::vector<char> input, std::string state, int position, int& cursorPos);
int main()
{
int tapeCount, position;
long long steps = 0;
std::string tape;
std::ifstream file("1.txt");
file >> tapeCount >> tape >> position;
std::vector <char> input(tape.begin(), tape.end());
std::vector <rule> rules;
rule temp;
while (file >> temp.qstate) {
file >> temp.csymbol;
file >> temp.nsymbol;
file >> temp.direction;
file >> temp.nstate;
rules.push_back(temp);
}
file.close();
position--; // kadangi masyvas skaiciuoja nuo nulio, tai ir startine pozicija sumazinu, kadangi ji skaiciuoja nuo vieno
int cursorPos = 0; // saugosim vieta, kurioje vietoje prasideda taisykles su reikiama busena
std::string state = "0"; // saugosim busena, kad zinotume, kokioje busenoje siuo metu esame
// Tiuringo masinos "algoritmas"
while (true) {
printingText(input, position, steps);
if (state == rules[cursorPos].qstate) {
if (input[position] == rules[cursorPos].csymbol) {
if (input[position] != rules[cursorPos].nsymbol) {
input[position] = rules[cursorPos].nsymbol;
if (rules[cursorPos].direction == 'L') {
position--;
steps++;
}
else if (rules[cursorPos].direction == 'R') {
position++;
steps++;
}
if (rules[cursorPos].nstate != state) {
state = rules[cursorPos].nstate;
}
}
else if (input[position] == rules[cursorPos].nsymbol) {
if (rules[cursorPos].direction == 'L') {
position--;
steps++;
}
else if (rules[cursorPos].direction == 'R') {
position++;
steps++;
}
if (rules[cursorPos].nstate != state) {
state = rules[cursorPos].nstate;
}
}
}
else if (input[position] != rules[cursorPos].csymbol) {
searchingForASymbolOrState(rules, input, state, position, cursorPos);
}
}
else if (state != rules[cursorPos].qstate) {
searchingForASymbolOrState(rules, input, state, position, cursorPos);
} // Skaiciuojam zingsnius
// std::cout << cursorPos << " " << position << " " << state << " " << rules[cursorPos].qstate; // Eilute naudojama klaidu paieskai
Sleep(100);
system("cls");
}
// "Algoritmo pabaiga"
}
void printingText(std::vector<char> input, int position, long long steps) {
std::cout << "Head position can be seen with '' symbols\n\n";
for (int i = 0; i < input.size(); i++) {
if (i == position) {
std::cout << "'" << input[i] << "'";
}
else {
std::cout << input[i];
}
}
std::cout << "\n\nSteps: " << steps;
}
void searchingForASymbolOrState(std::vector<rule> rules, std::vector<char> input, std::string state, int position, int& cursorPos) {
for (int i = 0; i < rules.size(); i++) {
if (rules[i].qstate == state) {
if (rules[i].csymbol == input[position]) {
cursorPos = i;
}
}
if (rules[cursorPos].qstate != state) {
if (rules[i].qstate == state) {
cursorPos = i;
}
}
}
}
I know that either .eof() or system("cls") aren't good functions to use, but for this project, I think they'll work fine. Correct me if I'm wrong.
EDIT: I tried to do something. Not sure if there's a more effective why. Obviously it's not finished, no halting and error checking and etc. But if you have any comments, they would be really appreciated.

Character counter returning incorrect value for char[n] array

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.

I have written this program for infix to postfix conversion

#include<iostream>
#include<stdio.h>
#define MAX 20
using namespace std;
char stk[MAX];
int top=-1;
void push(char c)
{
if(top==MAX-1)
cout<<"Overflow";
else
{
stk[++top]=c;
}
}
char pop()
{
if(top==-1)
{
return '\0';
}
else
return stk[top--];
}
int priority(char ch)
{
if(ch=='(')
return 1;
if(ch=='+'||ch=='-')
return 2;
if(ch=='*'||ch=='/')
return 3;
if(ch=='^')
return 4;
}
int main()
{
char exp[35],*t,x;
cout<<"Enter expression: ";
fgets(exp,35,stdin);
t=exp;
while(*t)
{
if(isalnum(*t))
cout<<*t;
else if(*t=='(')
push(*t);
else if(*t==')')
{
while((x=pop())!='(')
cout<<x;
}
else
{
if(priority(stk[top])>=priority(*t))
cout<<pop();
push(*t);
}
t++;
}
while(top!=-1)
cout<<pop();
return 0;
}
The output for input:
a+b-(c+d/e)
is
ab+cde/+
-
I don't understand why - is on a newline.
I have just started learning c++ and I am trying to implement some programs I did in c using c++. The same code in c works fine. I think there are some holes in my basic c++ knowledge and I would like to fill them up.
std::fgets does not discard the newline in the input stream like getline would. That means exp contains "a+b-(c+d/e)\n" and not "a+b-(c+d/e)". You either need to remove the newline from exp, switch to cin.getline(), or stop your processing loop when it hits the newline.
Try to change fgets to std::cin. And use std::string instead of char*:
#include <iostream>
#include <string>
int main()
{
string exp;
cout << "Enter expression: ";
std::cin >> exp;
auto t = exp.data();
char x;
for(auto &ch: exp)
{
if(isalnum(ch))
cout << ch;
else if(ch == '(')
push(ch);
else if(ch == ')')
{
while((x = pop()) != '(')
cout << x;
}
else
{
if(priority(stk[top]) >= priority(ch))
cout << pop();
push(ch);
}
}
while(top != -1)
cout << pop();
return 0;
}
In addition to the processing of '\n' as mentioned by NathanOliver, your function priority() doesn't return a value when the user entered any other character not checked in the if statements, so the behavior might be undefined.

I am getting a segmentation fault in this code and can't understand why?

I am trying to code a program where it takes a program as an input and prints out all the comments written in that program in a separate line.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
string str;
while(getline(cin,str)) {
int i;
// cout<<str;
for(i=0;str[i]!='/' && str[i+1] !='/';i++);
//cout<<i;
for(i;str[i]!='\n';i++) {
// cout<<i;
cout<<str[i];
}
cout<<endl;
}
return 0;
}
I am getting a segmentation fault in this code and I can't understand why. This is part of a code of a problem in hackerrank https://www.hackerrank.com/challenges/ide-identifying-comments/copy-from/12957153
As commented in your question your code is wrong. First you are treating std::string object, returned by getline, as character array. Secondly your for loops never end if there is no // or \n found in input string. So obviously it will crash. Below is the modified code.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
string str;
while(getline(cin,str)) {
int i;
// cout<<str;
size_t len = str.length();
const char *cstr = str.c_str();
for(i=0; (cstr[i]!='/' && cstr[i+1] !='/' && i < len); i++)
//cout<<i;
for(; cstr[i]!='\n' && i < len;i++) {
// cout<<i;
cout<<cstr[i];
}
cout<<endl;
}
return 0;
}
int main() {
while(getline(cin,str)) {
int i, len = str.size();
//always make sure that you are not accessing
//contents after your string has ended
for(i=0; i < (len - 1) && !(str[i] == '/' && str[i+1] == '/'); i++);
//note that i here might be the last alphabet
//if there's no comment
if(i < len && str[i] != '/')
i++;
//checking if str[i] != '\n' is not a good idea
//as c++ stl strings are not temrinated by '\n'
if(i < len) {
for(; i < len; i++)
cout << str[i];
cout << endl;
}
}
return 0;
}
Also note that both of the following codes won't terminate at the 4th character, c++ stl strings are not terminated by these characters.
string str = "hahahaha";
str[4] = '\n';
cout << str;
str[4] = '\0';
cout << str;
This is much easier to write and probably much faster than the other solutions to date.
#include <iostream>
int main()
{
std::string str;
while (std::getline(std::cin, str))
{
size_t loc = str.find("//");
if (loc != str.npos)
{
std::cout << str.substr(loc + 2)<< std::endl;
}
}
return 0;
}
It is also wrong.
Here is a nice, clean, and simple state machine version. Also pretty close to worst-case for speed. Thing is it's closest to being right, even though it is also wrong.
#include <iostream>
enum states
{
seeking1,
seeking2,
comment
};
int main()
{
std::string str;
while (std::getline(std::cin, str))
{
states state = seeking1;
for (char ch:str)
{
switch (state)
{
case seeking1:
if (ch == '/')
{
state = seeking2;
}
break;
case seeking2:
if (ch == '/')
{
state = comment;
}
else
{
state = seeking1;
}
break;
case comment:
std::cout << ch;
break;
}
}
if (state == comment)
{
std::cout << std::endl;
}
}
return 0;
}
Why are these approaches all wrong? Consider the line
cout << "Hi there! I am \\Not A Comment!" << endl;`
You can't just look at the \\, you also need the context. This is why the state machine above is the better option. It can be modified to handle, at the very least, states for handling strings and block comments.

Returning string from a function causing formatting issues

It's supposed to look like this: http://i.imgur.com/gko501E.png
Instead it looks like this: http://i.imgur.com/ISwqyD8.png
When I take the code out of the function and use it in the main class it works properly. However once I put it in this function the formatting problems occur, it also isn't filtering like it's supposed to. This program is supposed to take user input, store it in a string, remove all non-alphabetical characters, capitalize the vowels, and then space it out based on user defined variables given in the command line. It's also supposed to accept files as input in the command line, such as: 'program 5 8 < file'.
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <cstdlib>
#include <fstream>
#include <sstream>
using namespace std;
//make vowels uppercase
string filter(string input)
{
size_t found = input.find_first_of("aeiou");
while (found != string::npos)
{
if (islower(input[found]))
{
input[found] = toupper(input[found]);
found = input.find_first_of("aeiou", found + 1);
}
}
//Make consonants lowercase
size_t foundLower = input.find_first_of("BCDFGHJKLMNPQRSTVWXYZ");
while (foundLower != string::npos)
{
if (isupper(input[foundLower]))
{
input[foundLower] = tolower(input[foundLower]);
foundLower = input.find_first_of("BCDFGHJKLMNPQRSTVWXYZ", foundLower + 1);
}
}
//remove punctuation
for (int i = 0, len = input.size(); i < len; i++)
{
if (!isalnum(input[i]))
{
input.erase(i--, 1);
len = input.size();
}
}
return input;
}
int main(int argc, char* argv[])
{
int wordSize;
int wordSizeCounter;
int wordCounter = 0;
int rowSize;
//char letter;
wordSize = atoi(argv[1]);
rowSize = atoi(argv[2]);
ifstream inFile;
inFile.open(argv[3]);//open the input file
stringstream strStream;
strStream << inFile.rdbuf();//read the file
string test = strStream.str();//str holds the content of the file
if (!inFile) test = cin.get() ; // Read first character
//Begin filter for files
while (!test.empty())
{
filter(test);
if (test.length() < wordSize) //make sure we don't go out-of-bounds
{
wordSize = test.length();
}
cout << test.substr(0, wordSize);
cout << " ";
if (test.length() >= wordSize) //again, make sure we don't go out-of-bounds
{
test = test.substr(wordSize);
}
else
{
test = " ";
}
wordCounter++;
if (wordCounter == rowSize)
{
cout << std::endl;
wordCounter = 0;
}
if(test.empty())
{
test = cin.get();
}
}
cout << endl;
return 0;
}