Can someone please show me how to create an array function that reads from file txt string data type
for example:
Read in the following files inside of a function:
colleges.txt
states.txt
Add the colleges/universities to a vector of strings.
Add the states to parallel arrays of strings.
Call the read function from your main function.
Thank you very much :D
Try the following code:
#include<iostream>
#include<string>
#include<fstream>
#include<vector>
void func()
{
std::ifstream fin;
fin.open("colleges.txt", std::ifstream::in);
std::vector<std::string> vec;
std::string line;
while(getline(fin, line))
{
vec.push_back(line);
}
fin.close();
int len = vec.size();
std::string *arr = new std::string[len];
int index = 0;
fin.open("states.txt", std::ifstream::in);
while(getline(fin, line))
{
arr[index++] = line;
}
fin.close();
for(auto e:vec) std::cout<<e<<" ";
std::cout<<"\n";
for(int i = 0; i < len; ++i)
std::cout<<arr[i]<<" ";
std::cout<<"\n";
delete [] arr;
}
int main()
{
func();
return 0;
}
use vectors, Carl!
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;
struct TwoVectors {
vector<string> first ;
vector<string> second;
};
TwoVectors getSomeData() {
TwoVectors ret;
auto collegesReader = ifstream("colleges.txt");
auto statesReader = ifstream("states.txt");
string temp;
while (getline(collegesReader, temp))
ret.first.push_back(temp);
while (getline(statesReader, temp))
ret.second.push_back(temp);
collegesReader.close();
statesReader.close();
return ret;
}
int main() {
auto someData = getSomeData();
for (auto something : someData.first)
cout << something << endl;
for (auto something : someData.second)
cout << something << endl;
return 0;
}
Related
Having trouble compiling program. Should read input from text file and store into a dynamic array of structure. I'm prettty sure my problem lies in the ipod_Initialize function. I'm not sure how to pass the dynamic array structure through the function.
#include <iostream>
#include <string>
#include <fstream>
# include <ctime>
using namespace std;
struct Song
{
string title;
string artist;
float size{};
};
int song_Count(string);
void ipod_Initialize(string, int, Song);
void show_playlist();
int main(char *argv[]) {
// argv is filename
int count = song_Count(argv[1]);
Song* songInfo = new Song[count];
ipod_Initialize(argv[1], count, *songInfo);
cout << songInfo[0].title;
delete[] songInfo;
return 0;
}
int song_Count(string fileName){
ifstream inFile;
string data;
int count = 0;
inFile.open(fileName);
if (!inFile.is_open()){
cout << "Error opening file" << endl;
return 0;
}
while(!inFile.eof()){
getline(inFile, data);
if (!data.empty()){
count++;
}
}
inFile.close();
count = count / 3 + 1;
return count;
}
void ipod_Initialize(string fileName, int count, Song* songInfo) {
string data;
ifstream inFile;
inFile.open(fileName);
for (int i = 0; i <= count; i++) {
getline(inFile, data);
if (!data.empty())
songInfo[i].title = data;
getline(inFile, data);
if (!data.empty())
songInfo[i].artist = data;
//getline(inFile, mem);
if (!data.empty())
inFile >> songInfo[i].size;
}
}
I wrote the following code for removing the duplicates from a given string i.e. if ARRUN is the input then the output will be ARUN.
#include <bits/stdc++.h>
using namespace std;
char* removeDuplicates(string &s,int n){
char arr[n];
unordered_map<char,int> exists;
int index = 0;
for(int i=0;i<n;i++){
if(exists[s[i]]==0)
{
arr[index++] = s[i];
exists[s[i]]++;
}
}
return arr;
}
//driver code
int main(){
string str;
cin >> str;
cout<<removeDuplicates(str,str.length())<<endl;
return 0;
}
The code produces no output at all, however, it works fine if I use char arr[] instead of string class.
You can't use char arr[n] without being n constant or constexpr.
You don't need map. set is sufficient.
Note that map and set remove duplicates already, then you can check if any element is inserted or not to get your new string in the same order of the first, as follows
#include<string>
#include<iostream>
#include<unordered_set>
std::string removeDuplicates(const std::string &s){
std::string arr;
std::unordered_set<char> exists;
for(const auto&el:s)
if(exists.insert(el).second) arr+=el;
return arr;
}
//driver code
int main(){
std::string str;
std::cin >> str;
std::cout<<removeDuplicates(str)<<std::endl;
return 0;
}
std::string support removing elements.
#include <iostream>
#include <string>
std::string removeDuplicates(std::string str) {
for (int i = 0; i < str.size(); i++) {
while (true) {
int j = str.find_last_of(str[i]);
if (i < j) {
str.erase(j, 1);
} else {
break;
}
}
}
return str;
}
int main() {
std::cout << removeDuplicates("ARRUN");
return 0;
}
If a function declaration looks the following way
char* removeDuplicates(string &s,int n);
then it means that the passed object itself will be changed in the function. Otherwise the parameter shall have the qualifier const.
Also it is unclear why the function has return type char *. It looks like the declaration of the function is contradictive.
The second parameter of the function shall have at least the type size_t or that is better std::string::size_type. The type int can not accomodate all values of the type std::string::size_type.
The function could be declared without the second parameter.
A straightforward approach without using intermediate containers that requires dynamic memory allocation can look the following way
#include <iostream>
#include <string>
std::string & removeDuplicate( std::string &s )
{
const char *p = s.c_str();
std::string::size_type pos = 0;
for ( std::string::size_type i = 0, n = s.size(); i < n; i++ )
{
std::string::size_type j = 0;
while ( j < pos && s[i] != s[j] ) j++;
if ( j == pos )
{
if ( i != pos ) s[pos] = s[i];
++pos;
}
}
return s.erase( pos );
}
int main()
{
std::string s( "H e l l o" );
std::cout << "\"" << s <<"\"\n";
std::cout << "\"" << removeDuplicate( s ) <<"\"\n";
return 0;
}
The program output is
"H e l l o"
"H elo"
#Arun Suryan, You pointed out correctly. But you can do it without using vector by using global char array.
Also don't forget to append the newline at the end!
Have a look at the following code:
#include<string>
#include<iostream>
#include<unordered_map>
char* removeDuplicates(std::string &s,int n){
std::unordered_map<char,int> exists;
char* arr = (char*)(malloc(n*sizeof(char)));
int index = 0;
for(int i=0;i<n;i++){
if(exists[s[i]]==0)
{
arr[index++] = s[i];
exists[s[i]]++;
}
}
arr[index] = '\n';
return arr;
}
//driver code
int main(){
std::string str;
std::cin >> str;
std::cout<<removeDuplicates(str,str.length())<<std::endl;
return 0;
}
This might be a bit advanced for newcomers to C++ but another solution makes use of the erase-remove idiom:
std::string removeDuplicates(const std::string& s) {
std::string result = s;
std::unordered_set<char> seen;
result.erase(std::remove_if(result.begin(), result.end(), [&seen](char c)
{
if (seen.find(c) != seen.end())
return true;
seen.insert(c);
return false;
}),
result.end());
return result;
}
It basically uses a set to store characters that have been seen, shuffles the characters to be removed down to the tail (using std::remove_if) and erases the tail from the string.
Working version here.
This works too, a single line solution with an inbuild function.
cout<<str.erase(std::unique(str.begin(), str.end()), str.end());
Simple Answer
#include<bits/stdc++.h>
using namespace std;
string removeduplicate(string key){
set<char>s;
string ans="";
for(int i=0;i<key.size();++i){
if(s.find(key[i])==s.end()){
s.insert(key[i]);
ans.push_back(key[i]);
}
}
return ans;
}
int main()
{
string key="";
cout<<"enter the key:";
cin>>key;
string ans1=removeduplicate(key);
cout<<ans1;
return 0;
}
So, after doing a bit of reading on the Internet I realized that I was trying to return a pointer to the local array in the removeDuplicates() function.
This is what works fine
#include <bits/stdc++.h>
using namespace std;
void removeDuplicates(string &s,int n){
vector<char> vec;
unordered_map<char,int> exists;
int index = 0;
for(int i=0;i<n;i++){
if(exists[s[i]]==0)
{
vec.push_back(s[i]);
exists[s[i]]++;
}
}
for(auto x: vec)
cout << x;
}
//driver code
int main(){
string str;
cin >> str;
removeDuplicates(str,str.length());
return 0;
}
PS: We can make the return type of function to vector as well.
Hey so I'm very new to c++ and trying to convert a word a user enters to all uppercase
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int size=10;
int i =0;
char arr[size];
cout<<"Enter a word"<<endl;
cin.get(arr,size);
for(i = 0; i < 10; i++)
{
if(islower(arr[i]))
{
cout<<toupper(arr[i])<<endl;
}
}
return 0;
}
I'm getting numbers when I run this. What do I fix?
Don't write C-like C++, use the standard library to your advantage. Use an std::string and do something like this instead:
#include <iostream>
#include <algorithm>
#include <string>
int main() {
std::string input;
std::cin >> input;
std::transform(input.begin(), input.end(), input.begin(), ::toupper);
std::cout << input << std::endl;
return 0;
}
Or alternatively with a lambda:
std::transform(input.begin(), input.end(), input.begin(), [](unsigned char c){ return std::toupper(c); });
It is the time to learn one of bit-wise applications
#include <iostream>
#include <string>
int main()
{
int mask = 0xDF;
std::string str = "aBcdeqDsi";
for(int i(0); i < str.size(); ++i)
std::cout << static_cast<char>(str[i] & mask);
std::cout << std::endl;
return 0;
}
I am trying to convert strings of data to integers, (to use it for some calculations ) by using stringstream , but it fails when there is a space.
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string line;
vector <string>data;
for (int i = 0; i < 10;i++) {
getline(cin,line);
data.push_back(line);
}
///converting digits to int
vector<int> values;
int n;
char ch=',';
for (int i = 0; i < data.size();i++) {
stringstream stream(data[i]);
while( stream >>n ) {
if(stream >> ch) {
values.push_back(n);
}
else {
values.push_back(n);
}
cout<<n<<" ";
}
cout<<endl;
}
return 0;
}
input : 1,182,08 51 15 --> output : 1 182 8 1 5
there are some digits lost after spaces.
so, what can I do to avoid it?
Complete working code based on seccpur's answer. Visual Studio 2017 Community:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
#define BUFSZ 100 // Set max size of the numbers as a single string
int convertToIntegers(char *s, vector<int> &values);
int main()
{
int count;
int i;
char data[BUFSZ];
vector<int> values;
strcpy_s(data, "1,182,08 51 15");
count = convertToIntegers(data, values);
// for (auto val : values) // Show the result
// cout << val << '\n';
// *** OR ***
for (i = 0; i < count; i++)
cout << values[i] << '\n';
}
//////////////////////////////////////
// Convert a C string to integers
//
int convertToIntegers(char *s, vector<int> &values)
{
vector<string> numbers;
char *next_token;
char* ptr = strtok_s(s, " -.,;", &next_token);
while (ptr)
{
string str(ptr);
numbers.push_back(str);
ptr = strtok_s(NULL, " -.,;", &next_token); // Next number
}
//
// Convert the resulting strings to integers
//
for (auto str : numbers)
values.push_back(stoi(str));
return (int)values.size();
}
If you know you have exactly one character as a separator, either a space, either a comma, the following code will work:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string line;
vector <string>data;
for (int i = 0; i < 10;i++) {
getline(cin,line);
data.push_back(line);
}
///converting digits to int
vector<int> values;
int n;
char ch=',';
for (int i = 0; i < data.size();i++) {
stringstream stream(data[i]);
while( stream >>n ) {
char c = stream.get();
//if(stream >> ch) {
// values.push_back(n);
//}
//else {
values.push_back(n);
//}
cout<<n<<" ";
}
cout<<endl;
}
return 0;
}
You are using multiple delimiters in the input ( like whitespace : , ; -) which complicates the matter. Here's a possible snippet using std::strtok:
//Enter a line
string line;
getline(cin, line);
// Convert string to char* so that std::strtok could be used later
char *cstr = new char[line.length() + 1];
std::strcpy(cstr, line.c_str());
vector<string> words;
// split line into multiple strings using multiple delimiters
char* ptr = std::strtok(cstr, " -.,;");
while (ptr)
{
string str(ptr);
words.push_back(str);
ptr = strtok(NULL, " -.,;");
}
delete[] cstr;
// Convert string to int
vector<int> values;
for (auto str : words){
values.push_back(std::stoi(str));
}
// Print the values
for (auto val : values){
cout << val << '\n';
}
i'm fairly new to C++.
I want to write a Program/Function that checks a string input (from console or other source, not important here) if is already in an array. If it's not then it should be written into array. Otherwise do nothing.
My Problem is the for loop and if the if condition. What am I missing?
#include <iostream>
#include <string>
#include <fstream>
#include <stdio.h>
using namespace std;
typedef struct {
string id[10];
string foo1[10];
string type[10];
string func[10];
}Device;
int main() {
Device fooDevice;
string mystring;
int i = 0;
mystring = "foo";
ofstream temp;
temp.open("temp.txt", ios::out | ios::app);
for (fooDevice.id[i]; fooDevice.id[9]; i++) {
if (fooDevice.id[i] != mystring) {
fooDevice.id[i] = mystring;
temp << mystring << endl;
} else {
//do nothing
}
}
return 0;
}
The problem is the structure of your for loop. I'm not sure what you think your condition means, but here's how it should look:
for (std::size_t i = 0; i < 10; ++i) {
This increments the index value i from 0 to 9 (inclusive). You can then check the value of fooDevice[i].
At the moment, it seems you are trying to overwrite every element of the array with the new string. I'm not sure how you know how full the array is at any given time. Let's suppose you stop when you get to the first empty string:
for (std::size_t i = 0; i < 10; ++i) {
if (myString == fooDevice.id[i]) {
// already there, stop looping
break;
}
else if (fooDevice.id[i].empty()) {
// none of the currently set elements matches
fooDevice.id[i] = myString;
temp << myString << '\n';
break;
}
}
You could also replace this with a range-based-for:
for (auto& deviceId: fooDevice.id) {
if (myString == deviceId) {
// already there, stop looping
break;
}
else if (deviceId.empty()) {
// none of the currently set elements matches
deviceId = myString;
temp << myString << '\n';
break;
}
}
Better yet, use a std::vector with std::find from the <algorithm> header. (Warning: untested code):
struct Device {
// ...
std::vector<std::string> id;
// ...
};
// ...
auto foundId = std::find(fooDevice.id.begin(), fooDevice.id.end(), myString);
if (fooDevice.id.end() == foundId) {
// not already there
fooDevice.id.push_back(myString);
temp << myString << '\n';
}
It seems you are a bit confused about the difference between C and C++ as well:
The C++ version of <stdio.h> is <cstdio>, but you don't need it here at all (and you usually don't in a C++ program).
You don't need to typedef the name of a struct in C++, just do struct Device { ... };
And regarding C++ style, please reconsider your use of what are often considered bad practices: using namespace std; and endl.
for (fooDevice.id[i]; fooDevice.id[9]; i++) seems no scence. I think you want:
for(; i<9; ++i)
You can't use a string value as a loop condition. Only expressions that evaluate to booleans.
Also, you are also not initializing the device arrays before searching them.
Try something more like this:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct Device {
string id[10];
string foo1[10];
string type[10];
string func[10];
};
int main() {
Device fooDevice;
string mystring;
// fill fooDevice as needed...
mystring = "foo";
ofstream temp;
temp.open("temp.txt", ios::out | ios::app);
bool found = false;
int idx_available = -1;
for (int i = 0; i < 10; ++i) {
if (fooDevice.id[i] == mystring) {
//do nothing
found = true;
break;
}
if ((idx_available == -1) && fooDevice.id[i].empty())
idx_available = i;
}
if ((!found) && (idx_available != -1)) {
fooDevice.id[idx_available] = mystring;
temp << mystring << endl;
}
return 0;
}
Which would be better handled with some rewriting:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
struct Device {
std::string id;
std::string foo1;
std::string type;
std::string func;
};
struct isDeviceId {
const std::string &m_id;
isDeviceId(const std::string &id) : m_id(id) {
}
bool operator()(const Device &device) {
return (device.id == m_id);
}
};
int main() {
std::vector<Device> devices;
std::string mystring;
// fill devices as needed...
mystring = "foo";
if (std::find_if(devices.begin(), devices.end(), isDeviceId(mystring)) == devices.end()) {
Device device;
device.id = mystring;
devices.push_back(device);
std::ofstream temp;
temp.open("temp.txt", std::ios::out | std::ios::app);
temp << mystring << std::endl;
}
return 0;
}
Alternatively, in C++11 and later:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
struct Device {
std::string id;
std::string foo1;
std::string type;
std::string func;
};
int main() {
std::vector<Device> devices;
std::string mystring;
// fill devices as needed...
mystring = "foo";
if (std::find_if(devices.begin(), devices.end(),
[mystring&](const Device &device) { return (device.id == mystring); }
) == devices.end()) {
devices.emplace_back();
devices.back().id = mystring;
// or, in C++17:
// devices.emplace_back().id = mystring;
std::ofstream temp;
temp.open("temp.txt", std::ios::out | std::ios::app);
temp << mystring << std::endl;
}
return 0;
}