11 Replies - 758 Views - Last Post: 05 December 2016 - 11:08 PM Rate Topic: -----

#1 jv1597   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 143
  • Joined: 18-October 16

Problems accessing elements in a vector array

Posted 03 December 2016 - 11:50 PM

Hi all,
I'm having problems accessing elements in a vector array. I have tried around 5-10 different working approaches, but they won't work on my computer. I tried on online shells too. Maybe I'm doing something wrong. Can anyone tell me why the iterator won't work with the integer variable, delem?
        int i = 0;
        int elem = -specified at cin input-;
	int delem = elem - 1;
	vector<string>::iterator it = vs.begin() + delem;
	for (std::vector<string> it = vs.begin(); it != vs.end(); ++it, i++)
	{

		if (it == vs.begin())
		{
			edata += ",";
			vs.erase(it);
			vs.insert(it, 1, edata);
			break;
		}
		else
		{
			if (it != vs.begin())
			{
				edata = " " + edata;
				edata += ",";
				vs.erase(it);
				vs.insert(it, 1, edata);
				break;
			}
			else
			{
				edata = " " + edata;
				vs.erase(it);
				vs.insert(it, 1, edata);
				break;
			};
		};
	};
	copy(vs.begin(), vs.end(), ostream_iterator<string>(std::cout, " "));
	cout << '\n' << vs.at(3);



The lines should be something like:
Old Line:
john smith, num street, apt 2309, city, state, zip

New Line:
john smith, num street, "apt 4905," city, state, zip

Apartment element would be changed from "apt 2309," to "apt 4905," if I were to specify elem 3.
Any ideas?

Is This A Good Question/Topic? 0
  • +

Replies To: Problems accessing elements in a vector array

#2 Xupicor   User is offline

  • Nasal Demon
  • member icon

Reputation: 457
  • View blog
  • Posts: 1,179
  • Joined: 31-May 11

Re: Problems accessing elements in a vector array

Posted 04 December 2016 - 12:09 AM

vector<string>::iterator it = vs.begin() + delem;
You define it to be an iterator, ok...
for (std::vector<string> it = vs.begin(); it != vs.end(); ++it, i++)

For the body of that for loop the local it shadows the outer scope it. Do you really want that? Besides, you don't define inner scope it as an iterator but as a vector of strings. Do you really want that?

This post has been edited by Xupicor: 04 December 2016 - 12:11 AM

Was This Post Helpful? 0
  • +
  • -

#3 jv1597   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 143
  • Joined: 18-October 16

Re: Problems accessing elements in a vector array

Posted 04 December 2016 - 01:33 AM

Sorry about that, the line reads "for (std::vector<string>::iterator it = vs.begin(); it != vs.end(); ++it, i++)". I keep getting the same error message -- "the application has requested the Runtime to terminate it in an unusual way." etc...

Have you ever come across this message?
Was This Post Helpful? 0
  • +
  • -

#4 Xupicor   User is offline

  • Nasal Demon
  • member icon

Reputation: 457
  • View blog
  • Posts: 1,179
  • Joined: 31-May 11

Re: Problems accessing elements in a vector array

Posted 04 December 2016 - 01:39 AM

Sure I have, when I screwed up and the program crashed at runtime. ; )
Please paste shortest possible compilable program representing your case. Note that if that's your actual code above then you still shadow it variable with another it variable. So you loop through the whole vector since it in scope of the loop starts as an iterator "looking at" vs.begin(), and not as the shadowed outer scope it that you initialize with vs.begin() + delem.

Again, to stress it, you have TWO variables, both called it - but the inner scope one (the one defined in your for) shadows the outer scope one. Get rid of the outer scope one and properly initialize the inner scope one.

This post has been edited by Xupicor: 04 December 2016 - 01:45 AM

Was This Post Helpful? 0
  • +
  • -

#5 jv1597   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 143
  • Joined: 18-October 16

Re: Problems accessing elements in a vector array

Posted 04 December 2016 - 03:11 AM

This is the code in a nutshell. Preliminary input for line, element, and new data... Vector array build... Array revision.
#include <iostream>
#include <fstream>
#include <istream>
#include <ostream>
#include <sstream>
#include <string>
#include <locale>
#include <iomanip>
#include <limits>
#include <algorithm>
#include <iterator>
#include <stdio.h>
#include <cstdint>
#include <string.h>
#include <vector>
using namespace std;


	struct csv_whitespace: std::ctype<char>
	{
		static const mask* make_table()
		{
		// make a copy of the "C" locale table
		static std::vector<mask> v(classic_table(), classic_table() + table_size);
		v[','] |= punct; // comma will be classified as whitespace
		v[' '] &= ~space; // space will not be classified as whitespace

		return &v[0];
		}
		csv_whitespace(std::size_t refs = 0) :	ctype(make_table(), false, refs){}
	};


int main() {
	int elem = 0;
	int wrtln = 0;
	string edata;


	// PRELIMINARY INPUT CONSOLE
	cout << "Please enter line to write to:  ";
	cin >> wrtln;
	cout << '\n' << "Please enter the element you would like to access:  ";
	cin >> elem;
	cout << '\n' << "Please enter the new data to replace the old element with:  ";
	cin.get();
	getline(cin, edata);


	// LINE SEARCH FOR STORED DATA
	string str;
	ifstream ifs("test.txt", std::ios_base::in);
	for (int i = 0; i < wrtln - 1; i++) {
		ifs.ignore(numeric_limits<streamsize>::max(), '\n');
	};
	getline(ifs, str);
	ifs.close();


	// STRING STREAM INITIALIZATION
	string tkn;
	istringstream is(str);
	is.imbue(locale(is.getloc(), new csv_whitespace));


	// VECTOR ARRAY APPENDATION
	vector<string> vs;
	while (is >> tkn)
	{
		vs.push_back(tkn);
	}
	copy(vs.begin(), vs.end(), ostream_iterator<string>(std::cout, " "));


	int delem = elem - 1;
	std::vector<string>::iterator it = vs.begin() + delem;
	if (it != vs.begin())
	{
		edata = " " + edata;
		edata += ",";
		vs.erase(it);
		vs.insert(it, 1, edata);
	}
	else if (it == vs.begin())
	{
		edata += ",";
		vs.erase(it);
		vs.insert(it, 1, edata);
	}
	else if (it == vs.end())
	{
		edata = " " + edata;
		vs.erase(it);
		vs.insert(it, 1, edata);
	};
	copy(vs.begin(), vs.end(), ostream_iterator<string>(std::cout, " "));
	//cout << '\n' << vs.at(3);

/*

	// TO CONSOLE
	ostringstream os;
	copy(vs.begin(), vs.end(), ostream_iterator<string>(os, " "));
	cout << '\n' << "The revised element, element " << elem << ", in sequence container \"vs{}\" reads:  " << vs.at(delem) << '\n';


	// TO CONSOLE
	string vstr = os.str();
	cout << "Vector array sequence container \"vstr\" reads:  " << vstr << '\n';
*/

	return 0;
}


Was This Post Helpful? 0
  • +
  • -

#6 Xupicor   User is offline

  • Nasal Demon
  • member icon

Reputation: 457
  • View blog
  • Posts: 1,179
  • Joined: 31-May 11

Re: Problems accessing elements in a vector array

Posted 04 December 2016 - 03:18 AM

$ g++ --pedantic -Wall -Wextra -std=c++14 jv1597.cpp && ./a
Please enter line to write to:  2

Please enter the element you would like to access:  4

Please enter the new data to replace the old element with:  newdata
Segmentation fault
Hmm...
	ifstream ifs("test.txt", std::ios_base::in);
	for (int i = 0; i < wrtln - 1; i++) {
		ifs.ignore(numeric_limits<streamsize>::max(), '\n');
	};
	getline(ifs, str);
Oops. You don't check if the file exists. Also, you didn't provide needed example file. ;P
Was This Post Helpful? 0
  • +
  • -

#7 jv1597   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 143
  • Joined: 18-October 16

Re: Problems accessing elements in a vector array

Posted 04 December 2016 - 03:50 AM

The lines in the file consist of address info for different individuals, as follows:

1st name, 1232 ctry sq dr., apt 231, city, tx, 95865
2nd name, 6512 square dr., apt 6512, diff city, tx, zip
3rd name, 9851 sq dr., apt 564, etc city, tx, zip
4th name, 6515 country square dr., 321, city, state, zip
5th name, new street addr, apt ifany, new city, state, zip
6th name, diff street addr, apt ifany, diff city, diff state, zip

So you can cut/paste if you have to. As far as specifying whether the file exists, I can get that in, isn't it just:

if(testfile.is_open()) {}


Was This Post Helpful? 0
  • +
  • -

#8 Xupicor   User is offline

  • Nasal Demon
  • member icon

Reputation: 457
  • View blog
  • Posts: 1,179
  • Joined: 31-May 11

Re: Problems accessing elements in a vector array

Posted 04 December 2016 - 06:54 AM

Sorry for making you wait for so long - it's Sunday and all. :)

You can shorten it to if (testfile) { /* it's open */ } else { /* not open */ }.

Anyway, let's take a look:
$ g++ --pedantic -Wall -Wextra -std=c++14 -g jv1597.cpp && gdb ./a
//...
(gdb) break 73
Breakpoint 1 at 0x40193a: file jv1597.cpp, line 73.
(gdb) run
Starting program: J:\projects\experiments\a.exe
[New Thread 10780.0x3288]
warning: Can not parse XML library list; XML support was disabled at compile time
Please enter line to write to:  [New Thread 10780.0xdf0]
2

Please enter the element you would like to access:  2

Please enter the new data to replace the old element with:  hell
2nd name, 6512 square dr., apt 6512, diff city, tx, zip
Thread 1 hit Breakpoint 1, main () at jv1597.cpp:75
75              int delem = elem - 1;
(gdb) next
76              std::vector<string>::iterator it = vs.begin() + delem;
(gdb)
77              if (it != vs.begin())
(gdb)
79                      edata = " " + edata;
(gdb)
80                      edata += ",";
(gdb)
81                      vs.erase(it);
(gdb)
82                      vs.insert(it, 1, edata);
(gdb)
warning: Critical error detected c0000374

Thread 1 received signal SIGTRAP, Trace/breakpoint trap.
0x000007ff75a59cdc in ?? ()
(gdb)

It bugs out on insert. Well, let's look closer at what you're doing there... You erase an element using an iterator, and then you try to insert data using the very same iterator... But you can't do that!
http://en.cppreferen...er/vector/erase
As you can see, you can't do that because erase:

Quote

Invalidates iterators and references at or after the point of the erase, including the end() iterator.

That iterator is invalid after erase, and thus it all crashes and burns.

Also, the last branch (else if (it == vs.end())) will never be executed (let's forget about what it does for now) - since if it == vs.end() then it != vs.begin() and thus the first branch will get executed.

On that point...:
(gdb)
77              if (it != vs.begin())
(gdb) p it
$1 = {_M_current = 0xa14fa0}
(gdb) p vs.end()
$2 = {_M_current = 0xa14fa0} //whoops!?
(gdb) p vs.size() 
$3 = 1 // well heck, looks like some parsing didn't work!


Let's confirm that. I added a call to one of my util functions: xupi::print(vs); and what I see is:
$ g++ --pedantic -Wall -Wextra -std=c++14 -g -Og -fno-inline-functions -Wfatal-errors  jv1597.cpp && ./a <in
Please enter line to write to:
Please enter the element you would like to access:
Please enter the new data to replace the old element with:
2nd name, 6512 square dr., apt 6512, diff city, tx, zip
std::vector< std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > {
        0:      [ 2nd name, 6512 square dr., apt 6512, diff city, tx, zip  ]
}
So the splitting you wanted didn't quite work. Again, let's confirm:
$ g++ --pedantic -Wall -Wextra -std=c++14 -g -Og -fno-inline-functions -Wfatal-errors  jv1597.cpp && gdb ./a
//...
(gdb) break main
Breakpoint 1 at 0x401611: file jv1597.cpp, line 37.
(gdb) run
Starting program: J:\projects\experiments\a.exe
[New Thread 12632.0x316c]
warning: Can not parse XML library list; XML support was disabled at compile time

Breakpoint 1, main () at jv1597.cpp:37
37      int main() {
(gdb) next
38              int elem = 0;
(gdb)
39              int wrtln = 0;
(gdb)
40              string edata;
(gdb)
44              cout << "Please enter line to write to:  ";
(gdb)
Please enter line to write to:  45              cin >> wrtln;
(gdb)
[New Thread 12632.0x33c4]
2
46              cout << '\n' << "Please enter the element you would like to access:  ";
(gdb)

Please enter the element you would like to access:  47          cin >> elem;
(gdb)
2
48              cout << '\n' << "Please enter the new data to replace the old element with:  ";
(gdb)

Please enter the new data to replace the old element with:  49          cin.get();
(gdb)
50              getline(cin, edata);
(gdb)
hell
54              string str;
(gdb)
55              ifstream ifs("test.txt", std::ios_base::in);
(gdb)
57                      ifs.ignore(numeric_limits<streamsize>::max(), '\n');
(gdb)
56              for (int i = 0; i < wrtln - 1; i++) {
(gdb)
59              getline(ifs, str);
(gdb)
60              ifs.close();
(gdb)
64              string tkn;
(gdb)
65              istringstream is(str);
(gdb)
66              is.imbue(locale(is.getloc(), new csv_whitespace));
(gdb)
70              vector<string> vs;
(gdb)
71              while (is >> tkn)
(gdb)
73                      vs.push_back(tkn);
(gdb) p tkn
$1 = {
  static npos = 18446744073709551615,
  _M_dataplus = {
    <std::allocator<char>> = {
      <__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
    members of std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider:
    _M_p = 0x664f10 "2nd name, 6512 square dr., apt 6512, diff city, tx, zip "
  },
  _M_string_length = 56,
  {
    _M_local_buf = "8\000\000\000\000\000\000\000\000ļO\000\000\000\000",
    _M_allocated_capacity = 56
  }
}
(gdb) p tkn.c_str()
$2 = 0x664f10 "2nd name, 6512 square dr., apt 6512, diff city, tx, zip "

Well, well. I believe you can take it from here?
Was This Post Helpful? 0
  • +
  • -

#9 jv1597   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 143
  • Joined: 18-October 16

Re: Problems accessing elements in a vector array

Posted 04 December 2016 - 09:48 PM

Well, the 'while' statement was ok... I think the debug information is saying:

1) pointer "p", at "token" = "no data fields"
(that means it's done passing the data fields from the stream)

2) c_str() pointer, being "p token.c_str()" at 0x664f10 = "2nd name, 6512 square dr., apt 6512, diff city, tx, zip "
(that means the c_str() data for token at 'pointer token' is as follows)

3) "one element found", being "0: [ 2nd name, 6512 square dr., apt 6512, diff city, tx, zip ]"
(then, lastly, at the output, the debugger says, "one element found", which is the entire string data)

So it doesn't say much, but you might have a point on the iterator, having expired. It being an index value, it would take the stream from begin() to end() within standard <char> memory, and not within pointer memory.

Theory:
So the iterator goes to 'it', performs the erase, then requires a new iteration to reset to begin() once again for the insert.
Was This Post Helpful? 0
  • +
  • -

#10 Xupicor   User is offline

  • Nasal Demon
  • member icon

Reputation: 457
  • View blog
  • Posts: 1,179
  • Joined: 31-May 11

Re: Problems accessing elements in a vector array

Posted 04 December 2016 - 11:39 PM

What "pointer p"? There's no "pointer p". p in gdb is a shorthand for print, a command to print data. I'm printing your tkn string just after it has been modified by operator>>.
With your custom locale it looks like operator>> consumes the whole line, and doesn't "tokenize" at a comma.

Quote

It being an index value
Who said it's an index value? The rest of the sentence I won't even try to act as if I understand. What's "standard <char> memory"? What's "pointer memory"? O_O

Quote

So the iterator goes to 'it', performs the erase, then requires a new iteration to reset to begin() once again for the insert.
What? I... no.* The iterator it is invalidated after the call to erase. You can't use it anymore, unless you assign it a new, proper value (you get that from container methods).
I don't quite understand why you need to erase and insert elements - do you not want to modify an element? You can do that by just a simple assignment. But before you do that you need to fix your parsing.

*) unless by "requires a new iteration" you mean it needs to be assigned a new iterator, then sure. But that's a mighty confusing thing to say. An "iteration" already has a meaning.

This post has been edited by Xupicor: 04 December 2016 - 11:41 PM

Was This Post Helpful? 0
  • +
  • -

#11 jv1597   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 143
  • Joined: 18-October 16

Re: Problems accessing elements in a vector array

Posted 05 December 2016 - 02:04 AM

Xupicor, thanks for your reply...

Quote

With your custom locale it looks like operator>> consumes the whole line, and doesn't "tokenize" at a comma.


As far as I can tell the following sets the comma to whitespace, and reinserts the punctuation back into the string:

v[','] |= punct; // comma will be classified as whitespace



The line after that declassifies space " " as whitespace, without any insertion. I think with anything other than 'space' locale, the struct inserts either a space, or a punctuation, but with the 'space' locale it either leaves the space, when declassified, or consumes it when classified as whitespace.


Quote

Who said it's an index value? The rest of the sentence I won't even try to act as if I understand. What's "standard <char> memory"? What's "pointer memory"? O_O


My theory:
The character indexes, such as begin()/end() parameters, are character indexes in standard byte iteration, while pointer indexes such as seekg/tellg are pointer indexes for standard bit iteration in memory.

Pointer indexes, such as those used with 'operator[]', are utilized by the stream for character block assignment as bit values which point to the byte specified by '[i]', whether it be the first character in a string, or a specific character in the sequence. Such as with *it, or *p, these would be bit iterations pointing to the 'it' character index allocation.

The character indexes are utilized as a linear reference for character block assignment as byte values, which correspond to the 'std::distance' relative to begin()/end() bytes in memory. So these only work from beginning to end, then need to be re-instantiated for reuse, as the have no bit iteration place-holders in memory.

So what I was trying to say is that the iterator is invalidated, and requires a new instantiation to set the character index pointer back to begin().
Was This Post Helpful? 0
  • +
  • -

#12 jv1597   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 143
  • Joined: 18-October 16

Re: Problems accessing elements in a vector array

Posted 05 December 2016 - 11:08 PM

Thanks for you input... I finally got it working smoothly. I had a lagging comma issue, but I got it resolved. I just used a simple if/else algorithm to get passed the comma appendation on the last element in the array. So it works really well now, and I'm able to revise individual elements efficiently.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1