char*-Array as Parameter - c++

I want to put the following code in a function: (The code isn't complete, but I think it should be clear to you)
char *parsedData[SEPERATOR];
for(int i=0; i<SEPERATOR; i++)
{
parsedData[i]=tmp;
}
The function should look like the following:
int main()
{
char *parsedData[SEPERATOR];
Parser(WTString, parsedData);
}
int Parser(char *WTString, *parsedData[SEPERATOR])
{
for(int i=0; i<SEPERATOR; i++)
{
parsedData[i]=tmp;
}
}
The code works fine in one function. By dividing the code in two functions I got no usable data.
I would be grateful if someone could help me. I don't want to use further libraries.

If you don't want to use stl, I propose this function:
int PointToDefault(char* target, char** parsedData, unsigned int count)
{
for (unsigned int i=0; i<count; i++)
{
parsedData[i] = target;
}
}
and this call:
#define SEPERATOR 15
int main()
{
char tmp[] = "default string";
char *parsedData[SEPERATOR];
PointToDefault(tmp, parsedData, SEPERATOR);
}

char *parsedData[SEPERATOR]; Why?
Why do you need to use a raw array of pointers to char in C++?
Why don't you just use a std::vector<std::string> and spare yourself a whole load of misery and despair.

A C++ way of doing it would look like this:
#include <string>
#include <vector>
std::vector<std::string> Parser(const char *WTString)
{
std::vector<std::string> result;
for(std::size_t i = 0; i != SEPERATOR; ++i)
{
result.push_back(tmp); // whatever tmp is
}
return result;
}
I dont want to use further librarys.
Don't worry, my code sample only requries the standard library.

Related

Linear Search of a Const Char* array

I'm trying to do a linear search of a const char* array of strings that I have and am having a though time understanding what is wrong here.
The array is in a .h file and looks like this:
#pragma once
#include <iostream>
#include <string>
using namespace std;
const char* names[] = { "rodger", "michael", "tina", "jose", "chris", "andrew" };
And the code that I'm using for my linear search looks like this:
int linear_search(int array[], int size, int value) {
for (int i = 0; i < size; i++) {
if (value == names[i]) {
return i;
}
}
}
The compiler gives me the error that I can't compare int types and const char types, but how do I go about this if my array is of strings? Not just integers?
It looks like you're trying to search for a given value. Since your array is a n array of char* you need to compare two char* together using strcmp.
https://www.cplusplus.com/reference/cstring/strcmp/
As a side note, you're using c++ to it makes more sense to use std::string than char*
You have to adapt your search routine to char array:
int linear_search( const char* array[], int size, const char* value) {
for (int i = 0; i < size; i++) {
if ( ::strcmp( value, array[i] ) == 0 ) {
return i;
}
}
// Need to flag invalid or not found
return -1;
}

error: variable or field 'Palindrome' declared void in c++

I'm getting this error hence I am new to c++ I could not understand
please help me!!!
I am writing a palindrome code
This is the code given below:.............
I am basically here using some extra concepts not doing in-direct fashion.
if anyone can post the correct code he/she is most welcome...
//palindrome
#include <cstring> //or use #include <string.h>
#include <iostream>
using namespace std;
void Palindrom(string& );
void Palindrome(string& word)// same as (const string& word)
{
int n = word.length();
string word2;
char reverse[n];
for(int i = 0; i <=n; i++){
word[i]=tolower(word[i]);
}
word2=word; //now both are small
for(int i = n-1; i >=0; i--){
reverse[n-1-i]=word2[i];
cout<<reverse[n-1-i];
}
for(int i =0; i >n; i++){ //printing reversed
cout<< " Reverse: "<<reverse[i]<<endl;
}
// word is ok and word2 gets reversed
for (int i = 0; i <= n; i++){
if(word[i]==reverse[i])
{
cout<<"\nit is palandrome ";
}
cout<<"\nit is not a palindrome ";
}
}
int main()
{ string k="YuUuy";
void Palindrome(k);
return 0;
}
Correct syntax for calling a function is Palindrome(k); without the void.
Few remarks:
Get a good c++
book.
// same as (const string& word) is not true.
You did not include <string> header.
It's good practice to use std::size_t for indices, but beware of unsigned>=0 condition being always true.
char reverse[n]; is wrong, n must be a compile-time constant, VLA are not part of the C++ standard.
Function calls should not have return type. Change void Palindrome(k); in main() function to Palindrome(k);
While declaring array, the expression should have constant value. So you can't use char reverse[n];. Change it to char *reverse = new char[n]; and deallocate it using delete[] reverse; after you are done using it.
I would recommend you to use smart pointer. You should also take a look at std::string instead of using stream of char.

C++: Using loops and variable patterns (sequence)

I have a routine function process_letter_location(const char& c, string &word).
Inside my main I have declared a series of string variables like so:
string sf_1 = "something", sf_2 = "something", sf_3 = "something",
sf_4 = "something";
And i have a string word and i call my routine function as so
process_letter_location(word[0], sf_1);
process_letter_location(word[1], sf_2);
process_letter_location(word[2], sf_3);
process_letter_location(word[3], sf_4);
This does look a bit messy but i know i can use a loop to call the routine like
for(int i=0; i < 4; i++) {
process_letter_location (word[i], ?)
}
But I'm not so sure how i would go about assigning the second argument. The variables have 'sf_' in common and the only thing that change are the numbers. Is there anyway that i can incorporate this routine call in the loop? If not are there better ways of implementing this code?
Any help would be appreciated.
Thanks
You can use an array:
string sf[4] = { "something1", "something2", "something3", "something4"};
Then loop:
for(int i=0; i < 4; i++) {
process_letter_location (word[i], sf[i]);
}
You should use an array. Your use case screams it should be an array.
But if you can only change how you process the variables, you can use a variadic template function as well.
#include <iostream>
#include <string>
#include <type_traits>
using namespace std;
void process_letter_location(char c, string const& str)
{
cout << str << '\n';
}
void process_strings(char* buf, string const& str)
{
process_letter_location(*buf, str);
}
template<typename... Args>
auto process_strings(char* buf, string const& str, Args... args)
-> typename enable_if<sizeof...(Args)>::type
{
process_letter_location(*buf, str);
process_strings (++buf, args...);
}
int main() {
string sf_1 = "something1",
sf_2 = "something2",
sf_3 = "something3",
sf_4 = "something4";
char buff[10];
process_strings(buff, sf_1, sf_2, sf_3, sf_4);
return 0;
}
Which is just a fancy way to unroll the loop. See here
You can start with this refactoring: replace string with string * const
in the function process_letter_location. (Adjust the function definition
accordingly).
Then you can fill your favourite container with the string pointers
and loop on it.
I think you can learn a lot of C++ from this refactoring.
Let me show how you could write the loop:
std::vector<std::string*> strings = {&sf_1,
&sf_2,
&sf_3,
&sf_4};
for(int i=0; i < 4; i++) {
process_letter_location (word[i], strings[i]);
}
then you may consider using iterators rather than a C-style loop.

Determining why C++ program chrashes

I'm doing a C++ project for a PCB assembly thesis and I have been given (by my professor) an old set of C++ code. When I try test and run the code it chrashes...the program compiles ok, but it chrashes at runtime..here is the code:
main.cpp:
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>
#include <climits>
#include "NozzleBank.h"
#include "PlacementHead.h"
int main (int argc, char * const argv[]) {
std::vector<char> list;
for (int i=0; i<3; i++) {list.push_back('a');}
for (int i=0; i<3; i++) {list.push_back('b');}
for (int i=0; i<3; i++) {list.push_back('c');}
for (int i=0; i<3; i++) {list.push_back('d');}
for (int i=0; i<3; i++) {list.push_back('_');}
int i = 0;
char set[list.size()];
while (!list.empty()) {
int x = (rand() % list.size());
set[i] = list.at(x);
list.erase(list.begin()+x);
i++;
}
NozzleBank bank(15,set);
PlacementHead head(4,2,1,"abababab");
return 0;
}
PlacementHead.cpp:
#include "PlacementHead.h"
#include <string>
#include <iostream>
#include <string.h>
PlacementHead::PlacementHead(int width, int height, int gap, char* s) {
width_ = width;
height_ = height;
gap_ = gap;
size_ = (width*height)+1;
set_ = new char[size_];
from_ = new int[size_];
original_ = new char[size_];
strcpy(set_,s);
strcpy(original_,s);
}
PlacementHead::~PlacementHead() {
}
int PlacementHead::getSize() { return size_; }
int PlacementHead::getHeight() { return height_; }
int PlacementHead::getWidth() { return width_; }
int PlacementHead::getGap() { return gap_; }
// Palauttaa indeksissä i olevan suuttimen
char PlacementHead::getNozzle(int i) {
return set_[i-1];
}
// Asettaa indeksissä i olevan suuttimen
void PlacementHead::setNozzle(int i, char c) {
set_[i-1] = c;
}
// Merkitsee suuttimen poimituksi poistamalla sen listasta
void PlacementHead::markNozzle(int i, int bankPos) {
set_[i-1] = ' ';
from_[i-1] = bankPos;
}
// Palauttaa seuraavan poimimattoman suuttimen indeksin
int PlacementHead::getNextUnmarkedPos() {
for (int i=0; i<size_; i++) {
if (set_[i]!=' ') {
return i+1;
}
}
return 0;
}
// Palauttaa suuttimen alkuperäisen sijainnin pankissa
int PlacementHead::getBankPos(int i) {
return from_[i-1];
}
// Plauttaa alkuperäisen ladontapaan suutinjärjestyksen
void PlacementHead::reset() {
//for (int i=0; i<size_; i++) {
// set_[i] = original_[i];
//}
strcpy(set_,original_);
}
// Tulostusmetodi
void PlacementHead::print() {
std::cout << "ladontapää:\n";
for (int h=height_; h>0; h--) {
for (int w=width_; w>0; w--) {
int i = ((h-1)*width_)+w;
std::cout << getNozzle(i);
}
std::cout << "\n";
}
}
NozzleBank.cpp:
#include "NozzleBank.h"
#include <string>
#include <iostream>
#include <string.h>
NozzleBank::NozzleBank(int size) {
bank_ = new char[size];
original_ = new char[size];
size_=size;
for (int i=0; i<size_; i++) {
bank_[i] = ' ';
original_[i] = ' ';
}
}
NozzleBank::NozzleBank(int size, char* s) {
bank_ = new char[size];
original_ = new char[size];
size_ = size;
strcpy(bank_,s);
strcpy(original_,s);
}
NozzleBank::~NozzleBank() {
}
int NozzleBank::getSize() { return size_; }
// Palauttaa pankin alkuperäisen järjestyksen
void NozzleBank::reset() {
strcpy(bank_,original_);
}
// Asettaa indeksissä i olevan suuttimen
void NozzleBank::setNozzle(int i, char c) {
bank_[i-1] = c;
original_[i-1] = c;
}
// Palauttaa indeksissä i olevan suuttimen
char NozzleBank::getNozzle(int i) {
return bank_[i-1];
}
// Poimii suuttimen poistamalla sen listasta
void NozzleBank::pickNozzle(int i) {
bank_[i-1] = ' ';
}
// Tulostusmetodi
void NozzleBank::print() {
for (int i=size_; i>0; i--) {
std::cout << bank_[i-1];
}
}
When I run the program I get the following:
Now here is also an interesting thing: IF I switch the order of the following lines in main.cpp
NozzleBank bank(15,set);
PlacementHead head(4,2,1,"abababab");
to:
PlacementHead head(4,2,1,"abababab");
NozzleBank bank(15,set);
The program runs fine...:O? And here I get like whaaaat...I'm a bit newbie in C++ so I'd appreciate if someone could see what's the problem :) Thank you for any help!
The C library strcpy() requires a NUL terminated C style string. You have a char[] array that does not have a NUL terminator.
If you want to convert your randomized array of letters into a C-style string, you need to add one more element to the end, and set it to the value 0. Alternately, you need to turn your strcpy() calls into memcpy() calls and supply the length directly.
In terms of minimal code changes, adding a NUL terminator requires the fewest changes to your code. Change this:
char set[list.size()];
to this:
char set[list.size() + 1];
set[list.size()] = 0;
And then change all of your new char[size_] calls to new char[size_ + 1].
The cleaner approach would be to say what you mean, and treat this as an array of char, not a C string. Convert all your strcpy calls to memcpy. For example, this:
strcpy(set_,s);
strcpy(original_,s);
becomes this:
memcpy(set_,s,size_);
memcpy(original_,s,size_);
Note: Be sure to change all strcpy to memcpy on these arrays. I think there is at least one other. I did not check your code that closely.
The latter is the better approach, IMHO, but I offer both.
Also, the above code leaks memory. That may not be a concern if it just runs through once and quits. You new [] memory that you never delete []. If your program is going to grow and have multiple instances of these objects coming and going, you'll want to add those delete[] calls, otherwise you're setting yourself up for a future crash of a different sort.
One of the possible problems here is that you are using strcpy
strcpy works by reading an array of characters until it reaches a null terminating character '\0' - However your source array does not contain a null terminating character. so strcpy will keep copying forever, reading memory it doesn't have access to, and writing past the end of your destination array, either of which could cause the crash. You need to either use strncpy (which you should always prefer), which only copies a fixed number of characters.
You should in general always leave an extra space in any character array if you intend on treating the characters as a string, like strcpy does. If you are only using individual elements and treating the individual characters on their own, then you don't need to. You could equally use memcpy in that case.
There may be other problems in the code, this is just one I have spotted.
You also have memory leaks, you should delete[] the member variables you new[]

Preprocessor directive to create file names

I have to open files one by one for reading in C/C++. The name of the files are in0, in1, in2, in3.....
I tried to use preprocessor directive to create file names.
i want something like.
for(int i=0;i<n;i++)
{
string inp_file="/path/"+"in"+APPEND(i); //to generate /path/in1 etc
open(inp_file);
}
where APPEND is a MACRO.
Since
#define APP(i) i
can generate the value
#define APP(i) #i
can convert a token to string.
I am trying to combine them both in many ways but failed.
How to get the desired result or is it even possible to get the such a result with macro?
In your case, the variable i is not a compile-time constant and so it is impossible to use pre-processor or template specialization because the value is simply not known at a time of compilation. What you can do is convert integer into string - boost.lexical_cast is one of the easiest to use solutions:
for (int i = 0; i < n; ++i) {
// Generate /path/in1 etc
std::string inp_file = "/path/in"+ boost::lexical_cast<std::string>(i);
open(inp_file);
}
If you happen to have a compiler with C++11 support, you could use std::to_string(). For example:
for (int i = 0; i < n; ++i) {
// Generate /path/in1 etc
std::string inp_file = "/path/in" + std::to_string(i);
open(inp_file);
}
Hope it helps. Good Luck!
Addendum to Vlad's answer -- if for some reason you're not able/willing to use Boost, you can accomplish what you want using standard C++ with the stringstream class:
#include <sstream>
void Foo() {
for (int i = 0; i < n; ++i) {
std::stringstream converter;
converter << "/path/in" << i;
open(converter.str());
}
}
If you're not using boost, try this:
namespace StringUtils
{
// Converts any type which implements << to string (basic types are alright!)
template<typename T>
std::string StringUtils::toString(const T &t)
{
std::ostringstream oss;
oss << t;
return oss.str();
}
}
Use it this way:
for(int i=0;i<n;i++)
{
string inp_file="/path/"+"in"+ StringUtils::toString(i); //to generate /path/in1 etc
open(inp_file);
}
Just an addition to the existing answers which are all great, if you are using a newer compiler and standard library, c++11 introduces std::to_string(). So you can write code like this:
for(int i = 0; i < n; i++) {
string inp_file = "/path/in"+ std::to_string(i);
open(inp_file);
}
The C solution is this :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n =4;
char nstr[12];
sprintf(nstr, "%d", n);
int nlen = strlen( nstr );
const char *fd = "/path/in";
char buff[ strlen(fd) + nlen + 1 ];
sprintf( buff, "%s%d", fd, n );
/* for testing */
printf( "%s\n", buff );
}