Sscanf in a C++ (Read in values and assign simultaneously) - c++

Can I do something like this in C++ ?
//int i,Data[];
//malloc Data[];
$sscanf(line,"Data[%d]=0x%d",i,Data[i]);
Data[] is an int array and I am trying to read in random indices according to the value of 'i' I read in in one shot.

You can do it this way:
int index, value;
sscanf(line, "Data[%d]=%d", &index, &value);
// Check if index is within bounds of the array here
Data[index] = value;
You need the '&' because sscanf takes pointers as arguments.

Why not try it yourself? Don't forget you need to pass pointers to your values i.e.
sscanf(line, "Data[%d]=0x%d", &i, &Data[i]);
Whether or not it works (and it for the record, it doesn't), it makes for much more readable / safe code to do the assignment with a separate call (what happens if i is greater than the end of the array?):
const int maxData = 10;
int Data[maxData];
int i;
int tmp;
sscanf(line, "Data[%d]=0x%d", &i, &tmp);
if( i >= maxData )
{
printf("Error! index was too big");
}
else
{
Data[i] = tmp;
}
[Edit] # the down-voters: I know it doesn't work I was just trying to encourage the OP to try it for his/her self

Related

Is there a way in C++ to use a key word to determine array length?

I'm trying to make a function in C++ that will take a string input and use it to populate an array. The values that the array will be populated with are fixed, but it depends on the word passed in. Some of the elements stay the same, and some of them change. The array size is also dependent on the string that is passed in. I know I can do this by making two longer 'if' statements, but this method seems more efficent... if I can get it working. The code below is non-functioning, but it just to give a general idea of my headspace. Any help is appreciated. Thanks!
myString = "long";
if (myString == "short") {
int numArr* = new int[3];
numArr[2] = 0x02;
}
if (myString == "long") {
int numArr* = new int[5];
numArr[2] = 0x04;
numArr[4] = 0xA1;
numArr[5] = 0x32;
}
numArr[0] = 0x00;
numArr[1] = 0xFF;
numArr[3] = 0x50;
cout << numArr;
delete[] numArr;
First, to answer your question: Given a pointer-to-int (like numArr in your posted code), there is no portable way to query the size of the array that it points to (or even to verify that it actually points to an array at all!)
If you have a proper array, like this (not just a pointer), OTOH:
int properArray[6];
... a function like this will return the number of items in the array:
template<typename T, int size> constexpr unsigned int GetArraySize(T(&)[size])
{
return size;
}
unsigned int arraySize = GetArraySize(properArray); // sets arraySize to 6
That said, it seems to me the best way to make your code simpler and more efficient is to allocate a fixed-size array on the stack (large enough to handle your worst-case-scenario) and keep track of how many items in the array are actually being used, like this:
#include <string>
#include <iostream>
int main(int, char **)
{
int numArr[6] = {0x00, 0xFF, 0x00, 0x50, 0x00, 0x00};
int numValidArrayItems = 3;
std::string myString = "long";
if (myString == "short") {
numArr[2] = 0x02;
}
else if (myString == "long") {
numArr[2] = 0x04;
numArr[4] = 0xA1;
numArr[5] = 0x32;
numValidArrayItems = 6;
}
for (int i=0; i<numValidArrayItems; i++) std::cout << numArr[i] << "\n";
return 0;
}
That avoids the new and delete[] calls, which are likely to be the most expensive (and error-prone) parts of the posted code, and also avoids the need to query the numArr pointer to determine the size of the array it is pointing to.
int r[10];
int count = sizeof(r)/sizeof(r[0]);
cout<<count;
I saw only this type of solution, sorry. You can look at this thread and get better insight(if you wan to use function, for example)
Link for mentioned thread:
Element count of an array in C++

Returning a string * type array from a function back into the main

I'm new to C++ and I am working on a function to shuffle strings
It takes an array of strings, shuffles them, and returns them back to the main.
I am returning a pointer to an array of strings called shuffled. The problem I have is that when I try to save that new pointer to the array to another pointer in the main, I start getting weird values that either reference to a file location in my computer or a bunch of numbers.
I'll post the entire code here but really what you want to look at is the return types, how I return it and how I save it in main. Please tell me why my pointer is not referencing the working array that is created in the function. Here's the code:
#include <cstdio>
#include <string>
#include <ctime>
#include <new>
#include <cstdlib>
using namespace std;
const char * getString(const char * theStrings[], unsigned int stringNum)
{
return theStrings[stringNum];
}
string * shuffleStrings(string theStrings[])
{
int sz = 0;
while(!theStrings[sz].empty())
{
sz++;
}
sz--;
int randList[sz];
for(int p = 0; p < sz; p++)
{
randList[p] = sz;
}
srand(time(0));//seed randomizer to current time in seconds
bool ordered = true;
while(ordered)
{
int countNumberInRandList = 0;//avoid having a sz-1 member list length (weird error I was getting)
for(int i = 0; i < sz; i++)
{
int count = 0;
int randNum = rand()%(sz+1);//get random mod-based on size
for(int u = 0; u < sz; u++)
{
if(randList[u] != randNum)
{
count++;
}
}
if(count == sz)
{
randList[i] = randNum;
countNumberInRandList++;
}
else
i--;
}
//check to see if order is same
int count2 = 0;
for(int p = 0; p < sz; p++)
{
if(randList[p] == p)
{
count2++;
}
}
if(count2 < sz-(sz/2) && countNumberInRandList == sz)
{
ordered = false;
}
}
string * shuffled[sz];
for(int r = 0; r < sz; r++) //getting random num, and str list pointer from passed in stringlist and setting that value at shuffled [ random ].
{
int randVal = randList[r];
string * strListPointer = &theStrings[r];
shuffled[randVal] = strListPointer;
}
for(int i = 0; i < sz; i++)
{
printf("element %d is %s\n", i, shuffled[i]->c_str());//correct values in a random order.
}
return *shuffled;
}
int main()
{
string theSt[] = {"a", "b", "pocahontas","cashee","rawr", "okc", "mexican", "alfredo"};
string * shuff = shuffleStrings(theSt);//if looped, you will get wrong values
return 0;
}
Strings allocate their own memory, no need to give them the "length" like you would have to do for char arrays. There are several issues with your code - without going into the details, here are a few working/non-working examples that will hopefully help you:
using std::string;
// Returns a string by value
string s1() {
return "hello"; // This implicitly creates a std::string
}
// Also returns a string by value
string s2() {
string s = "how are you";
return s;
}
// Returns a pointer to a string - the caller is responsible for deleting
string* s3() {
string* s = new string;
*s = "this is a string";
return s;
}
// Does not work - do not use!
string* this_does_not_work() {
string s = "i am another string";
// Here we are returning a pointer to a locally allocated string.
// The string will be destroyed when this function returns, and the
// pointer will point at some random memory, not a string!
// Do not do this!
return &s;
}
int main() {
string v1 = s1();
// ...do things with v1...
string v2 = s2();
// ...do things with v2...
string* v3 = s3();
// ...do things with v3...
// We now own v3 and have to deallocate it!
delete v3;
}
There are a bunch of things wrong here -- don't panic, this is what happens to most people when they are first wrapping their brains around pointers and arrays in C and C++. But it means it's hard to put a finger on a single error and say "this is it". So I'll point out a few things.
(But advance warning: You ask about the pointer being returned to main, your code does indeed do something wrong with that, and I am about to say a bunch of things about what's wrong and how to do better. But that is not actually responsible for the errors you're seeing.)
So, in shuffleStrings you're making an array of pointers-to-string (string * shuffled[]). You're asking shuffleStrings to return a single pointer-to-string (string *). Can you see that these don't match?
In C and C++, you can't actually pass arrays around and return them from functions. The behaviour you get when you try tends to be confusing to newcomers. You'll need to understand it at some point, but for now I'll just say: you shouldn't actually be making shuffleStrings try to return an array.
There are two better approaches. The first is to use not an array but a vector, a container type that exists in C++ but not in C. You can pass arrays around by value, and they will get copied as required. If you made shuffleStrings return a vector<string*> (and made the other necessary changes in shuffleStrings and main to use vectors instead of arrays), that could work.
vector<string *> shuffleStrings(...) {
// ... (set things up) ...
vector<string *> shuffled(sz);
// ... (fill shuffled appropriately) ...
return shuffled;
}
But that is liable to be inefficient, because your program is then having to copy a load of stuff around. (It mightn't be so bad in this case, because a smallish array of pointers isn't very large and because C++ compilers are sometimes able to figure out what you're doing in cases like this and avoid the copying; the details aren't important right now.)
The other approach is to make the array not in shuffleStrings but in main; to pass a pointer to that array (or to its first element, which turns out to be kinda equivalent) into shuffleStrings; and to make shuffleStrings then modify the contents of the array.
void shuffleStrings(string * shuffled[], ...) {
// ... (set things up) ...
// ... (fill shuffled appropriately) ...
}
int main(...) {
// ...
string * shuffled[sz];
shuffleStrings(shuffled, theSt);
// output strings (main is probably a neater place for this
// than shuffleStrings)
}
Having said all this, the problems that are causing your symptoms lie elsewhere, inside shuffleStrings -- after all, main in your code never actually uses the pointer it gets back from shuffleStrings.
So what's actually wrong? I haven't figured out exactly what your shuffling code is trying to do, but that is where I bet the problem lies. You are making this array of pointers-to-string, and then you are filling in some of its elements -- the ones corresponding to numbers in randList. But if the numbers in randList don't cover the full range of valid indices in shuffled, you will leave some of those pointers uninitialized, and they might point absolutely anywhere, and then asking for their c_strs could give you all kinds of nonsense. I expect that's where the problem lies.
Your problem has nothing to do with any of the stuff you are saying. As you are a beginner I would suggest not presuming that your code is correct. Instead I would suggest removing parts that are not believed to be problematic until you have nothing left but the problem.
If you do this, you should quickly discover that you are writing to invalid memory.
part two : you can't seem to decide on the type of what you are returning. Are you building a pointer to an array to return or are you returning an array of pointers.... you seem to switch between these intermittently.
part three : read #Gareth's answer, he explains about passing parameters around nicely for your instance.

Check array position for null/empty

I have an array which might contain empty/null positions (e.g: array[2]=3, array[4]=empty/unassigned). I want to check in a loop whether the array position is null.
array[4]==NULL //this doesn't work
I'm pretty new to C++.
Thanks.
Edit: Here's more code;
A header file contains the following declaration
int y[50];
The population of the array is done in another class,
geoGraph.y[x] = nums[x];
The array should be checked for null in the following code;
int x=0;
for(int i=0; i<sizeof(y);i++){
//check for null
p[i].SetPoint(Recto.Height()-x,y[i]);
if(i>0){
dc.MoveTo(p[i-1]);
dc.LineTo(p[i]);
}
x+=50;
}
If your array is not initialized then it contains randoms values and cannot be checked !
To initialize your array with 0 values:
int array[5] = {0};
Then you can check if the value is 0:
array[4] == 0;
When you compare to NULL, it compares to 0 as the NULL is defined as integer value 0 or 0L.
If you have an array of pointers, better use the nullptr value to check:
char* array[5] = {nullptr}; // we defined an array of char*, initialized to nullptr
if (array[4] == nullptr)
// do something
You can use boost::optional (or std::optional since C++17), which was developed in particular for decision of your problem:
boost::optional<int> y[50];
....
geoGraph.y[x] = nums[x];
....
const size_t size_y = sizeof(y)/sizeof(y[0]); //!!!! correct size of y!!!!
for(int i=0; i<size_y;i++){
if(y[i]) { //check for null
p[i].SetPoint(Recto.Height()-x,*y[i]);
....
}
}
P.S. Do not use C-type array -> use std::array or std::vector.
std::array<int, 50> y; //not int y[50] !!!
If the array contains integers, the value cannot be NULL. NULL can be used if the array contains pointers.
SomeClass* myArray[2];
myArray[0] = new SomeClass();
myArray[1] = NULL;
if (myArray[0] != NULL) { // this will be executed }
if (myArray[1] != NULL) { // this will NOT be executed }
As http://en.cppreference.com/w/cpp/types/NULL states, NULL is a null pointer constant!
There is no bound checking in array in C programming. If you declare array as
int arr[50];
Then you can even write as
arr[51] = 10;
The compiler would not throw an error. Hope this answers your question.

Converting integers into a char* c++

Here is the function I have, "Sprite" is an object in the program, and "GetSpriteAtPosition" just returns a pointer to the correct sprite at the coordinates.
My problem is that I store a letter in each sprite, in the form of an integer. 0 is a, and 25 is z, with everything in between respectively. I need my function to return a char* that gives me the letters of a row of sprites, so if in the program the sprites spell out "abcdefgh", then that's what I need this function to print out. There's an 8x8 grid of sprites, and I'm getting the coordinates correctly, but I get an error that I can't convert an int to a char* in the marked line. What can I do to get this to work?
Thanks in advance!
char* RowLetters(int row)
{
char* pointer;
for( int i = 0; i < 8; i++)
{
Sprite* selectedSprite = SpriteAtPosition(row*50, i * 50);
if(selectedSprite != NULL)
{
char* temp = (char)(selectedSprite->Frame() + 97); //error here
pointer = strcat(pointer, temp);
}
else
{
pointer = strcat(pointer, "test");
}
}
return pointer;
}
Try this:
char temp = (char)(selectedSprite->Frame() + 97);
pointer = strcat(pointer, &temp);
I've changed the variable into a standard char rather than a pointer and then passed a reference to strcat() with the & operator.
EDIT:
As pointed out in the comments, this doesn't work because &temp isn't NULL terminated. I used to get around this when I programmed more C by doing the following.
char temp[2];
temp[0] = (char)(selectedSprite->Frame() + 97);
temp[1] = '\0';
pointer = strcat(pointer, temp);
Of course, the temp array could be declared outside the for() loop for a little better performance (in theory).
None of this addresses the other problems with the code like pointer never being declared. I think a broader understanding of the calling function would be in order to determine whether pointer should be allocated within this function or passed in by the caller.
Your code as written, will have undefined behavior because pointer is not initialized, and does not point to any valid memory that you have allocated (to hold the appropriate length of letters in the row.
If this truly is C++, as you state, then you don't want to return a char* from this function, as that implies that you have a static string already allocated within that function (yuck), or you will be dynamically allocating the string in that function and the caller must free it (yuck).
Neither of these options is ideal.
I'd suggest a very simple change to return a std::string, like this:
std::string RowLetters(int row)
{
std::string pointer;
for( int i = 0; i < 8; i++)
{
Sprite* selectedSprite = SpriteAtPosition(row*50, i * 50);
if(selectedSprite != NULL)
{
pointer.push_back((char)(selectedSprite->Frame() + 97));
}
else
{
// ???
// pointer = strcat(pointer, "test");
}
}
return pointer;
}

Delete a record in an array

int i;
int Input;
cin >> Input;
for(i = 0; i < Size ; i ++ )
if (List[i].PersonID == Input) {
}
I am trying to make a function that deletes a record from the array based on the id input provided. I am not sure what to do beyond this here. Will I also need to shift the values in the array after a record is removed?
I can't tell what type your List is.
But you should go for something like this:
List.RemoveAt(i--);
List.DeleteAt(i--);
i-- will decrement i AFTER the function has been called.
You should not need to shift any values in the array if you are using the standard containers.
If you are responsible for the array, then you do need to shift your values.
** EDIT
Here is a link to an introduction to the standard containers. If you are managing your own dynamic array you should consider using these instead.
Here I'm assuming List is a primitive array of ints.
#include<algorithm> // where std::remove() resides
#include<iterator> // where std::distance() resides (not strictly necessary)
struct BadPerson {
BadPerson(int Bad) : Bad_(Bad) { }
bool operator()(const Element& Elem) const {
return Elem.PersonID == Bad_;
}
};
// ...
int *NewEnd = std::remove_if(List, List + ListLength, BadPerson);
// the list now has a new end, because elements were "removed".
// but they weren't really removed; the array still has the same fixed size.
int ListLength = std::distance(List, NewEnd);
I think the best way to remove elements from an array/vector is to use a copy approach with something like:
int write_ptr = 0;
for (int read_ptr=0; read_ptr < n; read_ptr++)
{
if (... keep element array[write_ptr] ? ...)
{
if (read_ptr != write_ptr)
array[write_ptr] = array[read_ptr];
write_ptr++;
}
}
// The new size of the array is write_ptr
This will allow to remove even multiple elements with just one pass.
The standard library includes this approach as std::remove_if, however until C++0X arrives it's annoying to use because of limitations of the language (the code needed to be able to specify the test becomes easily quite ugly).
int i;
int Input;
cin >> Input;
for(i = 0; i < Size ; i ++ )
{
if (List[i].PersonID == Input)
{
for(int j=i;j<size-1;j++)
{
List[j]=List[j+1];
}
}
}