I am new to c++ and I'm having a bit of trouble implementing my first program. I need to create a Line class which simply contains an array of char (c-string) as well as a length and a max capacity. The linePtr member variable is of type char*. Here is what I have:
Line.h:
#pragma once
#ifndef LINE_H
#define LINE_H
#include <iostream>
using namespace std;
class Line {
private:
char* linePtr{nullptr};
int lineLength;
int lineCapacity;
public:
Line(); //default ctor
Line(char);
~Line();
friend ostream& operator<<(ostream& output, const Line& l);
};
#endif // !LINE_H
Line.cpp:
#include <iostream>
#include <cstring>
#include "Line.h"
using std::cout;
using std::endl;
using std::strcpy;
using std::strlen;
const int LINE_CAPACITY = 5000; //arbitrarily set
Line::Line() {
cout << "Default ctor" << endl;
linePtr = new char[1]{ '\0' };
lineCapacity = LINE_CAPACITY;
lineLength = 0;
}
Line::Line(char cstr) {
cout << "ctor Line(char cstr)" << endl;
linePtr = new char[2];
lineCapacity = LINE_CAPACITY;
lineLength = 1;
linePtr[0] = cstr;
}
ostream& operator<<(ostream& out, const Line& l) {
return out << l.linePtr;
}
Main.cpp:
#include <iostream>
#include "Line.h"
using namespace::std;
int main() {
Line l1;
cout << l1 << endl;
Line l2('x');
cout << l2 << endl;
system("pause");
return 0;
}
When I run with debugging, when the linePtr field it is written I get the message: "Error reading characters of string". I'm sure I'm doing something stupid but I can't figure it out.
You're not null-terminating the character array in the second constructor. Add this line at the end of the method:
linePtr[1] = '\0';
Related
So I'm unable to create a substring cut using ranges. I am making an airport program where you feed the program a txt.file and it has to divide the lines I get from it into different strings. For instance, I have the following text data:
CL903 LONDON 41000 14.35 08906 //number of flight, destination, price, etc.
UQ5723 SYDNEY 53090 23.20 12986
IC5984 TORONTO 18030 04.45 03260
AM608 TOKYO 41070 18.45 11315
so the first string will be on the lines of this (variables are in Spanish):
numVuelo[n] = M[n].substr(0,5)
this line will work perfectly, but when I move to the next one (from 7 to 14), it tells me that it's out of range, even though It's between the 0 and 31st values of the length of the string.
M[n] gets all of the strings on the text, I'm using Codeblocks and a class style with header and all. I'll copy the code below...
This is my header Vuelo.h:
#ifndef VUELO_H
#define VUELO_H
#include <iostream>
#include <fstream>
#include <string>
#define NUM_FLIGHTS 10
using namespace std;
class Vuelo
{
public:
Vuelo(int N);
virtual ~Vuelo();
void setM();
void setNumVuelo(string _numVuelo, int n);
void setDestino(string _destino, int n);
void setPrecio(string _precio, int n);
private:
string M[NUM_FLIGHTS];
string numVuelo[NUM_FLIGHTS];
string destino[NUM_FLIGHTS+1]; //somehow "destino" doesn't work without the +1 but everything else does
float precio[NUM_FLIGHTS];
Then, on another code called Vuelo.cpp I have the following
#include "Vuelo.h"
Vuelo::Vuelo(int N)
{
M[N] = { };
numVuelo[N] = { };
destino[N] = { };
precio[N] = { };
}
Vuelo::~Vuelo()
{
//nope
}
void Vuelo::setM()
{
int c = 1;
string s;
ifstream F ("flights.txt");
if(F.is_open())
{
while (!F.eof())
{
getline(F,s);
M[c] = s;
cout << M[c] << endl;
c++;
}
//sets all values
for(c = 0; c < NUM_FLIGHTS; c++)
{
setNumVuelo(M[c],c);
setDestino(M[c],c);
setPrecio(M[c],c);
}
F.close();
}
else
{
cout << "ERROR document wasn't found" << endl;
}
}
void Vuelo::setNumVuelo(string _numVuelo, int n)
{
numVuelo[n]= _numVuelo.substr(0,5); //this works
cout << numVuelo[n] <<endl;
}
void Vuelo::setDestino(string _destino, int n)
{
destino[n] = _destino.substr(7, 13); //PROBLEM HERE
cout << destino[n] << " " << destino[n].length() << endl;
}
void Vuelo::setPrecio(string _precio, int n)
{
string p = _precio.substr(15,19); //PROBLEM HERE
precio[n] = atof(p.c_str());
cout << precio[n] <<endl;
}
And finally my main looks like this:
#include "Vuelo.h"
#include <iostream>
#include <fstream>
#include <string>
#define NUM_FLIGHTS 10
using namespace std;
int main()
{
cout << "Bienvenido, reserva tu vuelo!" << endl;
cout << "-----------------------------------" << endl;
Vuelo* flight = new Vuelo(NUM_FLIGHTS);
flight->setM();
return 0;
}
Thanks :)
i am writing a character pointer to a file, but my program always crashes at name when i do it and i am unable to figure out why
#include <iostream>
#include <iomanip>
#include <string>
#include "AmaProduct.h"
using namespace std;
namespace sict{
AmaProduct::AmaProduct(char file){
fileTag_ = file;
}
const char* AmaProduct::unit()const{
return unit_;
}
void AmaProduct::unit(const char* value){
for (int i = 0; i != 9; i++){
unit_[i] = value[i];
}
unit_[11] = 0;
}
fstream& AmaProduct::store(fstream& file, bool addNewLine)const{
file.open("file.txt");
if (file.is_open()){
file << fileTag_ << "," << sku() << ",";
file<< name() << ",";//here
file<< price() << "," << taxed() << "," << quantity() << "," << unit_ << "," << qtyNeeded();
if (addNewLine){
file << endl;
}
}
file.close();
return file;
}
header file
#ifndef SICT_AMAPRODUCT_H__
#define SICT_AMAPRODUCT_H__
#include "Streamable.h"
#include "Product.h"
#include "Date.h"
#include "ErrorMessage.h"
#include "general.h"
#include <iostream>
#include <fstream>
namespace sict{
class AmaProduct : public Product{
private:
char fileTag_;
char unit_[11];
protected:
ErrorMessage err_;
public:
AmaProduct(char file='N');
const char* unit()const;
void unit(const char* value);
fstream& store(fstream& file, bool addNewLine = true)const;
fstream& load(std::fstream& file);
ostream& write(ostream& os, bool linear)const;
istream& read(istream& is);
};
}
name()
const char* Product::name()const{
return name_;
}
char* name_;
void Product::name(char* name){
delete[] name_;
name_= new char[strlen(name)+1];
strcpy(name_,name);
}
if anyone is interested in the other files i will upload them too
There are several possibilities, but if cout<<name() causes a segmentation fault, the most probable cases are:
name_ is still nullptr
name_ is an invalid pointer (for example if you copied your structure, which doesn't respect the rule of 3)
To make your code more reliable, you could change all char*, their tedious memory allocations and the c-style string operations with string.
If you don't, make sure to respect the rule of 3 to avoid shallow copy and pointer issues when copying or copy constructing your struct, and make sure that when you use a fixed size char array, you're sure not to overflow the buffer
Note also that doing this, might overflow the buffer:
file.getline(n, ',');
name(n);
because istream::getline(), when it has two arguments, takes as second argument the size (here 44, the ascii value of the comma). file.getline(n, 7, ',') would be the correct form.
I'm stuck with error message deprecated conversion from string constant to 'char*'
What I tried to do here is to assign "First", "Last" to cfoo1 and make cfoo2 equal to cfoo1. Lastly, display cfoo1 and cfoo2 to standard output.
#include <iostream>
#include <cstring>
#include "cfoo.h"
using namespace std;
CFoo :: CFoo(char first[], char last[]){
m_first[BUF] = first[BUF];
m_last[BUF] = last[BUF];
}
void CFoo :: WriteFoo(){
cout << m_first[BUF] << ", " << m_last[BUF];
}
#ifndef CFOO_HEADER
#define CFOO_HEADER
#include <iostream>
#include <cstring>
using namespace std;
const int BUF = 256;
class CFoo{
public:
CFoo(char first[], char last[]);
void WriteFoo();
private:
char m_first[BUF];
char m_last[BUF];
};
#endif
#include <iostream>
#include "cfoo.h"
using namespace std;
int main(){
CFoo foo1("Jong", "Yoon");
CFoo foo2 = foo1;
cout << "foo1 = ";
foo1.WriteFoo();
cout << endl;
cout << "foo 2 = ";
foo2.WriteFoo();
cout << endl;
return 0;
}
There are two issues:
Using string literals (which are of type char const*) to call a function that expects char[].
Trying to assign to char arrays.
Fixes:
Change the constructor to:
CFoo(char const* first, char const* last);
Change its implementation to:
CFoo(char const* first, char const* last)
{
// Make sure to copy at most BUF-1 characters
// to m_first and m_last.
m_first[0] = '\0'
strncat(m_first, first, BUF-1);
m_last[0] = '\0'
strncat(m_last, last, BUF-1);
}
You also need to change the implementation of CFoo::WriteFoo() to use the entire string
void CFoo::WriteFoo()
{
cout << m_first << ", " << m_last;
}
Also,
Accessing m_first[BUF] or m_last[BUF] is an error since the maximum value of a valid index to access those arrays is BUF-1.
just a beginner student learning basic C++. I'm trying to figure out the best way to:
Turn a char array Name of 20 into a string that can be printed.
I found in other Stack Overflow topics to use "str()" such as "str(Name)", but it always comes up 'identifier not found'.
cout << "Name:" << str(Name) << endl;
Set a char array of 20 characters. For some reason, the following gives me errors when declaring. I've tweaked it so many times, but I cannot get why it won't give.
TESCStudent.Name[20] = {'S','u','p','e','r','P','r','o','g','r','a','m','m','e','r','\0'};
Full code I have so far:
#include <iostream>
#include <conio.h>
#include <string>
using namespace std;
//Step 1
struct StudentRecord
{
char Name[20];
//Accessor
void printInfo() const;
};
void StudentRecord::printInfo() const
{
cout << "Name:" << str(Name) << endl;
}
int main()
{
//Step 2
StudentRecord TESCStudent;
TESCStudent.Name[20] = {'S','u','p','e','r','P','r','o','g','r','a','m','m','e','r','\0'};
//Step 3
TESCStudent.printInfo();
_getch();
return 0;
}
Given that you are at a very beginner level, just use std::string:
#include <iostream>
#include <conio.h>
#include <string>
struct StudentRecord {
std::string Name;
void printInfo() const {
std::cout << "Name:" << Name << '\n';
}
};
int main() {
StudentRecord TESCStudent;
TESCStudent.Name = "SuperProgrammer";
TESCStudent.printInfo();
_getch();
}
Live demo
The syntax like this:
char Name[20] = {'S','u','p','e','r','\0'};
is used to initialize a variable when you define it. However, in your case,
StudentRecord TESCStudent;
TESCStudent.Name[20] = ...;
You've already defined it on the line before, so you can't "initialize", you have to "assign" it.
This is pretty much why you use std:string instead of char[].
I can get getline() to work with cin (getline(cin,line)), but when I open a stream, it won't read the line from the file. The file contains a list of elements from the periodic table.
for Example:
H
He
O
etc...
EDIT:
However, when I try to cout the newly read line, it doesn't put it into var symbol at the line:
cout << "symbol: " << symbol << endl;
It doesn't give me anything out, but it should return the first element (H).
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void print(vector <string> x)
{
cout << "list of elements:" << endl;
for (int i = 0; i < x.size(); ++i)
{
cout << x[i] << endl;
}
}
int main(int argc, char** argv)
{
string symbol;
vector <string> elementlist;
ifstream readin;
readin.open("Elements.txt");
getline(readin,symbol);
cout << "symbol: " << symbol << endl;
while (!readin.good())
{
elementlist.push_back(symbol);
getline(readin,symbol);
}
print (elementlist);
return 0;
}
I'd do it something like this:
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
class line {
std::string data;
public:
friend std::istream &operator>>(std::istream &is, line &l) {
std::getline(is, l.data);
return is;
}
operator std::string() const { return data; }
};
int main() {
std::ifstream readin("Elements.txt");
// Initialize vector from data in stream:
//
std::vector<std::string>
element_list((std::istream_iterator<line>(readin)),
std::istream_iterator<line>());
// write data from vector to cout:
//
std::copy(element_list.begin(), element_list.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
As I stated in my comment, your loop condition is wrong.
while (!readin.good())
{
elementlist.push_back(symbol);
getline(readin,symbol);
}
As it turns out, you want to loop using the condition readin.good(). Since !readin.good() will evaluate to false, you never actually enter the loop.