I was writing a program that went through a string but in the for loop it gave me an error and the answers online that I found used only vectors.
std::string str = "Test";
for (int i = 0, max = str.size; i < max; i++)
std::string::size is a member function, you need to call it:
for (int i = 0, max = str.size(); i < max; i++)
// ^^ here
... and in order to make the issue with signed-unsigned conversion go away:
for (std::size_t i = 0, max = str.size(); i < max; i++)
// ^^^^^^^^^^^ index type for standard library container
Besides, if you need to process every char in the string, consider using a range based for loop;
for (char c : str)
// ...
Related
I'm searching to initialize data of char type like below. but I'm not sure on how to do this
char* data[ ][ ] = {
{"", "index1", "clock1", "Rate1"},
{"", "index2", "clock2", "Rate2"},
{"", "index3", "clock3", "Rate3"},
{"", "index4", "clock4", "Rate4"}
}
so that when I want to assign data of above table to other variables like below
for( int i = 0; i < 6; i++)
{
char k[][];
for(int j = 0; j < 6; j++ )
{
k[i][j] = data[i][j];
}
}
and my expected output is like this
k[i][1] = "index1", k[i][2] = "clock1", k[i][3] = "Rate1"
k[i+1][1] = "index2", k[i+1][2] = "clock2", k[i+1][3] = "Rate2" etc.,
How could I initialize the variable data like above to get the values like mentioned in output?
A couple things to note in the k assignment loop. You are looping 0-6 when the array bounds defined in data are 0-3 (4 elements). You initialized k within your for loop. k will need bounds because it is not being initialized. Remember, arrays in C are of a fixed size. Here is the code I'm referring to:
for( int i = 0; i < 6; i++)
{
char k[][]; /* Re-initialize here? */
for(int j = 0; j < 6; j++ )
{
k[i][j] = data[i][j];
}
}
k will need to be initialized with bounds like this:
char* k[4][4];
Also, your assignment of data is not doing what you think it is. You want to initialize it like this:
char* data[4][4] = {
{{""}, {"index1"}, {"clock1"}, {"Rate1"}},
{{""}, {"index2"}, {"clock2"}, {"Rate2"}},
{{""}, {"index3"}, {"clock3"}, {"Rate3"}},
{{""}, {"index4"}, {"clock4"}, {"Rate4"}}
};
In reality though, this also is not going to be very helpful because, as I said above, arrays are of fixed size. Elements data[0][x] are all single element arrays of char. They will serve no purpose. I think you want to assign different strings to them. Assigning/accessing data[0][x][y] where y is greater than 0 will be undefined behavior. It looks like what you really need here is variable length strings. Since you tagged this question with C++, an easy C++ solution would be to use std::string here. If you really need totally variable length strings in C, you will need to use dynamic memory allocation. For a more simple approach, it would be better to assign data with a fixed string size. Later, if you want to assign different strings, you will want to use strcpy.
Below is a solution for you. I used 20 as the fixed string size. You may want more space.
#include<stdio.h>
int main(int argc, char** argv)
{
char data[4][4][20] = {
{{""}, {"index1"}, {"clock1"}, {"Rate1"}},
{{""}, {"index2"}, {"clock2"}, {"Rate2"}},
{{""}, {"index3"}, {"clock3"}, {"Rate3"}},
{{""}, {"index4"}, {"clock4"}, {"Rate4"}}
};
int i;
int j;
char* k[4][4];
for(i = 0; i < 4; i++)
for(j = 0; j < 4; j++ )
k[i][j] = data[i][j];
for (i = 0; i < 4; ++i)
for(j = 0; j < 4; ++j)
printf("%s\n", k[i][j]);
}
I am new to c++. I need help fixing this error:
Item.cpp: In member function ‘char* ict::Item::sku() const’:
Item.cpp:65:36: warning: comparison between signed and unsigned integer
expressions [-Wsign-compare]
This is the part of the code that is giving the error:
//in header file
char m_sku[MAX_SKU_LEN + 1];
//in cpp file
char* Item::sku() const
{
int length = strlen(m_sku);
char *arr = new char[length]();
for (int i = 0; i <= strlen(m_sku); i++) {
arr[i] = m_sku[i];
}
return arr;
}
The most straightforward way to fix this is to make i an unsigned variable instead of a signed one. You can use size_t to match the return type of strlen:
size_t length = strlen(m_sku);
char *arr = new char[length]();
for (size_t i = 0; i <= length; i++) {
arr[i] = m_sku[i];
}
But be careful since this same replacement doesn't work with loops that count down towards 0.
// oops! This is an infinite loop:
for (size_t i = length-1; i >=0; i--) {
arr[i] = m_sku[i];
}
Write a static cast (int)strlen(m_sku) or vice versa std::size_t i = 0.
So that compared items will be the same.
I just started with proggraming and i dont know what is happening here.I dont know why my Visual Studio give me error to pointed lines minmax (expression must be a pointer to a complete object type)
std::array<float, 2> *minmax(std::vector<float> v) {
int min = v.front();
for (int i = 0; i < v.size(); i++)
if (min > v.at(i))
min = v.at(i);
int max = v.front();
for (int i = 0; i < v.size(); i++)
if (max < v.at(i))
max = v.at(i);
minmax[0] = min; <-------
minmax[1] = max; <-------
}
There are a couple of things you need to change for this to compile: you haven't defined an array called "minmax", so you need to do that first, before you try to assign the values of min and max to it. Your function also doesn't return the array yet.
I know eventually I need to change trigram, whose one space contains 3 characters from the former string, into a dynamic array to solve this problem, but I tried to set my array's capacity large enough at first. However, when I compile my code, the error appears.
#error: variable length array of non-POD element type 'string' (aka 'basic_string<char>'#
Code:
//global variable
int CAPACITY = 1000;
int main()
{
//a string that reads in the language of the text
string language = "";
//a string that reads in the file name of the text
string filename = "text.txt";
//a string that reads in the original text characters
string original = "";
//a string that reads in the modified original array
string rid_of_spaces = "";
//an array with capacity that stores the trigrams
string trigrams[CAPACITY];
ifstream finput;
char c;
//the length of an array
int sLength = 0;
//the tracker for trigrams
int counter = 0;
cin >> language >> filename;
finput.open(filename.c_str());
while (finput.get(c)){
//to test if the character is alpha
if (isalpha(c)){
//change the alphabet to lowercase
c = tolower(c);
//store the modified letter in the array
original += c;
}
//change any other characters into a space
else original += ' ';
}
sLength = original.length();
//loop through the original array and change mutiple spaces into one
for (int i = 0; i < sLength; i++){
if (isalpha(original[i]))
rid_of_spaces += original[i];
else {
while (original[i] == ' ')
i++;
rid_of_spaces += ' ';
rid_of_spaces += original[i];
}
}
sLength = rid_of_spaces.length();
for (int i = 0; i < CAPACITY; i++)
trigrams[i] = 0;//initialize each element to 0
for (int i = 0; i < sLength - 2; i++){
trigrams[counter] += rid_of_spaces[i]
+ rid_of_spaces[i + 1]
+ rid_of_spaces[i + 2];
counter++;
}
cout << filename << endl;
cout << original << endl;
cout << rid_of_spaces << endl;
for (int i = 0; i < counter; i++)
cout << trigrams[i] << endl;
finput.close();
return 0;
}
The variable
int CAPACITY = 1000;
should be a constant
const int CAPACITY = 1000; // or with c++11 constexpr int CAPACITY = 1000;
for
string trigrams[CAPACITY];
because "ISO C++ forbids variable length array 'trigrams'" (g++ message)
And this
for (int i = 0; i < CAPACITY; i++)
trigrams[i] = 0;//initialize each element to 0
should be
for (int i = 0; i < CAPACITY; ++i)
trigrams[i] = "";//initialize each element to 0
You don't "initialize [strings] to 0" but with a zero length C-string. A zero length C-string is not an invalid 0-pointer, but a (valid) pointer to a char with value 0;
Generally, it's better not to use C-arrays if there are STL-means to avoid them; with c++11, std::array<std::string, CAPACITY> would be preferable here if you want to stay with the "capacity large enough" approach.
live at Coliru's
I took the liberty to change all i++ to ++i in the for-loops' heads while at it; see eg. What is the difference between ++i and i++ for the rationale behind that.
For a dynamic (without pre-defined bounds) array use std::vector<std::string> trigrams;,
push_back or emplace_back your strings into that vector,
and for i- iterate
for (std::size_t i = 0; i < trigrams.size(); ++i) {/* ... */}
Or use the iterator-interface of std::vector, e.g.
std::for_each(trigrams.begin(), trigrams.end(),
some_function_or_functor_that_does_the_job);
(see std::foreach here ),
or with c++11 just
for (auto& s : trigrams) {/* ... */}
unless you need to customize the iteration like you do it inside your second loop.
The variable CAPACITY is not a compile-time constant variable, and variable-length arrays are not in C++ (though some have it as an extension, but apparently not for all types).
There are two solutions to your problem:
Turn the variable into a compile-time constant, either by making it constexpr alternatively const (for older compilers), or by defining it as a preprocessor macro.
Use std::vector, like std::vector<std::string> trigram(CAPACITY);
My suggestion is that you use both solutions above, at least if you later need to resize the vector. If the size will be fixed at compile-time and never change, then use the first solution and use std::array instead of a C-style array:
constexpr std::size_t CAPACITY = 1000;
...
std::array<std::string, CAPACITY> trigram;
The size of a C++ array must be a constant expression. You declare it as int CAPACITY = 1000;, which is not a constant expression. Adding a const qualifier solves the issue: int const CAPACITY = 1000;.
However, you should avoid plain arrays. Try using std::array if you know the size at compile time, or std::vector if not.
I have an ini file with some hex characters,like this:
[FOO]
1=0x55
2=0x40
3=0x90
First, is this the right format for an ini file, or should i use \x50?
Second, how can i read the characters? i have this:
char Frame[4]
TIniFile* IniFile;
IniFile=new TIniFile(cPath+"\\"+"setup.ini");
for( int i = 1; i < 4; i++ )
{
Frame[i]=IniFile->ReadString("FOO",i,-1);
}
The problem is that IniFile->ReadChar doesn't exist (i am using borland c++ builder 6).
how can i cast the string (0x55 for example) to a char? so i can put it in the Frame array
The \x55 notation is typically used within string literals:
const char* s = "\x55";
When writing to a file 0x55 is common, but ultimately it is up to the code processing the file to know what it is consuming.
I cannot comment on IniFile but if you can manage to store the value into a char[] you can use std::strtol() to obtain the integer value:
const char* s = "0x55";
long value = std::strtol(s, 0, 16);
Also, note that the for loop is going beyond the bounds of array Frame as array indexes are zero based. The valid indexes for Frame are 0, 1 and 2 only but the loop would access 3 which is undefined behaviour. Change to:
for(int i = 0; i < 3; i++)
Note the for loop will not populate the first element of Frame, as array indexes are zero based (unsure if that is intentional).
Solution:
AnsiString string;
TIniFile* IniFile;
IniFile=new TIniFile(cPath+"\\"+"setup.ini");
for( int i = 1; i < 5; i++ )
{
string=IniFile->ReadString("FOO",i,-1);
Frame[i]=static_cast<char>(std::strtol(string.c_str(), 0, 16));
}
Since you are using the VCL, you can use the StrToInt...() family of functions, which support 0xXX notation in C++, and then cast the result to char, eg:
for( int i = 0; i < 4; i++ )
{
Frame[i] = (char) StrToIntDef(IniFile->ReadString("FOO", i+1, ""), -1);
}
Or:
for( int i = 0; i < 4; i++ )
{
Frame[i] = (char) IniFile->ReadString("FOO", i+1, "").ToIntDef(-1);
}