Char vector is modified on copying character in C++ - c++11

Following is my submission for
https://leetcode.com/problems/letter-combinations-of-a-phone-number
However I see very weird behavior on lines
char c = map1[s[i]][j];
t.replace(i,1,1,c);
The vector map1[s[i]] is changing size on execution of above line in the code below. How can character c be copied by value rather than reference. If I remove reference for string in function argument (meaning no &) everything works fine but it won't be the right way, since copying string by value is costly.
class Solution {
public:
string s;
vector<string> res;
unordered_map<char, vector<char>> map1;
void letterCombinations(string &t, int i){
char c;
if(s.size()==0)
return;
if(i==s.size())
res.push_back(t);
else{
for(int j=0;j<map1[s[i]].size();j++){
//cout<<"Starting:"<<map1[s[i]].size()<<endl;
char c = map1[s[i]][j];
t.replace(i,1,1,c);
letterCombinations(t, i+1);
//cout<<"Return:"<<map1[s[i]].size()<<endl;
}
}
}
vector<string> letterCombinations(string digits) {
stringstream t;
map1['1'] = vector<char>{};
map1['0'] = vector<char>{};
map1['2'] = vector<char>{'a','b','c'};
map1['3'] = vector<char>{'d','e','f'};
map1['4'] = vector<char>{'g','h','i'};
map1['5'] = vector<char>{'j','k','l'};
map1['6'] = vector<char>{'m','n','o'};
map1['7'] = vector<char>{'p','q','r','s'};
map1['8'] = vector<char>{'t','u','v'};
map1['9'] = vector<char>{'w','x','y','z'};
s=digits;
letterCombinations(s,0);
return res;
}
};

Related

wcstombs & allocating memory for character array on heap

I'm reading a file with a single wide character line in it. But, I never know how long it is going to be. I've read this into a std::wstring, inString, and have managed to create the multi byte string out of thin air (Q1 - are these called r-values?). Q2 - Now, how do I allocate memory for this in the heap and obtain a smart pointer to it ? I do not want to use new or malloc (and call free or delete eventually) or any constant to store it on the stack (for I can never know the max length). Q3 - Can I make use of the make_shared or make_unique function templates here ? Q4 - To be specific, can I get a pointer like shared_ptr<char> pointing to the char array allocated on the heap ?
I tried something like the following,
std::shared_ptr<char> MBString(const_cast<char*>(std::string(inString.begin(), inString.end()).c_str()));
it did not work. I tried a few suggestions on the internet but I don't know how to do it yet.
Q5 - Let alone Wide char to multi -byte conversion, in general, how do I allocate an arbitrary length char string on the heap and get a smart pointer to it ?
std::wfstream inFile(L"lengthUnkown.txt", std::ios::in);
std::wstring inString;
inFile >> inString;
std::wcout << inString << std::endl; //prints correctly
std::cout << (const_cast<char*>(std::string(inString.begin(), inString.end()).c_str())) << std::endl; //this prints the line correctly as expected
//convert wide character string to multi-byte on the heap pointed, to by MBString
//std::cout << MBString << std::endl; //I want to print the multi-byte string like this
return 0;
Not resource optimal but reliable:
wchar_t* mb2wstr(const char* inval) {
size_t size = std::strlen(inval);
#define OUTSZ (size+1)*sizeof(wchar_t)
auto buf = (wchar_t*)std::malloc(OUTSZ);
std::memset(buf, 0, OUTSZ);
std::setlocale(LC_CTYPE,""); // необходима, чтобы отработала "mbstowcs"
size = std::mbstowcs(buf, inval, size);
if ( size == (size_t)(-1) ) {
std::free(buf);
buf = nullptr;
} else {
buf = (wchar_t*)std::realloc(buf,OUTSZ);
}
return buf;
#undef OUTSZ
}
char* wstr2mb(const wchar_t* inval) {
size_t size = std::wcslen(inval);
#define OUTSZ (size+1)*MB_CUR_MAX // Maximum length of a multibyte character in the current locale
auto buf = (char*)std::malloc(OUTSZ);
std::memset(buf, 0, OUTSZ);
std::setlocale(LC_CTYPE,""); // необходима, чтобы отработала "wcstombs"
size = std::wcstombs(buf, inval, size*sizeof(wchar_t));
if ( size == (size_t)(-1) ) {
std::free(buf);
buf = nullptr;
} else {
buf = (char*)std::realloc(buf,size+1);
}
return buf;
#undef OUTSZ
}
const std::string pwchar2string(const wchar_t* inval) {
char* tmp = wstr2mb(inval);
string out{tmp};
std::free(tmp);
return out;
}
const std::wstring pchar2wstring(const char* inval) {
wchar_t* tmp = mb2wstr(inval);
wstring out{tmp};
std::free(tmp);
return out;
}
const wstring string2wstring(const string& value) {
return pchar2wstring(value.c_str());
}
const string wstring2string(const wstring& value) {
return pwchar2string(value.c_str());
}
const wchar_t* char2wchar(const char* value) {
return pchar2wstring(value).c_str();
}
const char* wchar2char(const wchar_t* value) {
return pwchar2string(value).c_str();
}

Pointer not printing char[] array

I'm writing some code to take in a string, turn it into a char array and then print back to the user (before passing to another function).
Currently the code works up to dat.toCharArray(DatTim,datsize); however, the pointer does not seem to be working as the wile loop never fires
String input = "Test String for Foo";
InputParse(input);
void InputParse (String dat)
//Write Data
datsize = dat.length()+1;
const char DatTim[datsize];
dat.toCharArray(DatTim,datsize);
//Debug print back
for(int i=0;i<datsize;i++)
{
Serial.write(DatTim[i]);
}
Serial.println();
//Debug pointer print back
const char *b;
b=*DatTim;
while (*b)
{
Serial.print(*b);
b++;
}
Foo(*DatTim);
I can't figure out the difference between what I have above vs the template code provided by Majenko
void PrintString(const char *str)
{
const char *p;
p = str;
while (*p)
{
Serial.print(*p);
p++;
}
}
The expression *DatTim is the same as DatTim[0], i.e. it gets the first character in the array and then assigns it to the pointer b (something the compiler should have warned you about).
Arrays naturally decays to pointers to their first element, that is DatTim is equal to &DatTim[0].
The simple solution is to simply do
const char *b = DatTim;

scanf,fgets, fgetc get skipped inside loop

Im trying to make a recursive menu.
This program will later work with a tree(hojanodo), thats why I keep track of the root.
Problem: For some reason the fgets/fgetc is being skipped inside the recursivity on the second run, why does this happen?
I want the user to input either 1,2 or 3.(int)
What would be the fix for this? and is this the best way to implement a menu?
Here's what I have right now:(It compiles and runs so you can test it out but doesn't really work like I would like to..)
#include<stdio.h>
#include<stdlib.h>
typedef struct node{
char ch;
int i;
struct node *left;
struct node *right;
}hojaNodo;
int handle_menu(int eventHandler, hojaNodo **root);
int opcion_menu();
char get_symbol();
int get_userMenuInput();
int intro();
int main(){
hojaNodo *treeRoot = NULL;
intro();
// system("clear");
handle_menu(opcion_menu(), &treeRoot);
return 0;
}
int opcion_menu(){
int userOption;
printf("1.Agrega un Simbolo.\n");
printf("2.Listar Codigo\n");
printf("3.Exit");
userOption = get_userMenuInput();
printf("User: %d",userOption);
if(userOption < 4 && userOption > 0){
return userOption;
}
else
return -1;
}//eof opcion_menu
int handle_menu(int userOption,hojaNodo **root){
hojaNodo *tempRoot = NULL;
tempRoot = *root;
int valor;
char simbol;
switch(userOption){
case 1:
simbol = get_symbol();
printf("Simbol: %c", simbol);
break;
case 2:
printf("List Nodes\n");
break;
case 3:
printf("Exit");
userOption = -1;
// destroy_tree(root);
break;
default:
printf("userOption Error, Bye!");
break;
}//eof switch
if(userOption != -1)
handle_menu(opcion_menu(),&tempRoot);
// return userOption;
return -1;
}//eof menu()
char get_symbol(){
/*char userKey[3]
fgets(userKey,len,stdin);*/
char simbolo;
printf("Give me a symbol.");
simbolo = fgetc(stdin);
return simbolo;
}
int get_userMenuInput(){
char userKey[3];
int userOption;
size_t len;
len = sizeof(userKey);
fgets(userKey,len,stdin);
userOption = atoi(userKey);
//printf("User Option: %d\n", userOption);
return userOption;
}
Well apart from all the comments related to recursion and other changes suggested, please check this out. fgets() function needs flushing the input stream. It can be done using fflush() or fgetc().
A simple solution would be:
In function:
int opcion_menu(){
...
fgets(userKey,2,stdin);
fgetc(stdin); // Add this statement
Also in function:
int handle_menu(int userOption,hojaNodo **root)
case 1:
printf("Give me a choice : ");
fgets(userKey,2,stdin);
fgetc(stdin); // add this statement
fgets reads in at most one less than size characters from stream and stores them into the buffer pointed to by string. This will lead the newline character still available in Input Stream which need to be flushed. If this newline character is not read from Input stream, than this would become the input for next fgets function and ultimately it will skip the fgets(since it has already got its input a newline character)
fgetc(stdin) will flush out these extra newline character.
I don't know if this might help anyone.
In my case, I had to 'free' the buffer from the char with this function:
void clean(){
char cTemp;
while((cTemp = getchar()) != '\n')
;
}
Im not really sure why this works but it does(if anyone does, please add it to my answer).
I call it right before I call get_userOption();

Having trouble implementing a linked list in c++

I am trying to implement a simple singly linked list of integers which are to be sorted upon insertion in Visual Studio c++ 2010 express.
The problem is that when I create a new node and call the .getValue() function on it, the correct number is returned, however somehow that is being lost when I try calling getValue() on a node already in the list. The node might not be inserted into the list correctly, however I can't find why that would be the case. Some other value which looks like a reference value or something is displayed instead of the correct value.
I added current to the watch window when debugging but was still unable to see any of my variables other than the give value to be inserted. I am new to visual studio so I'm not sure if I'm missing something there. Here is my code:
#include "Node.h";
#include <iostream>
//namespace Linked{
//The first two constructors would be the first in the linked list.
Node::Node(void){
value = 0;
next = 0;
}
Node::Node(int setValue){
value = setValue;
next = 0;
}
Node::Node(int setValue,Node *nextNode){
value = setValue;
next = nextNode;
}
Node * Node::getNext(){
return next;
}
void Node::setNext(Node newNext){
next = &newNext;
}
int Node::getValue(){
return value;
}
bool Node::isEqual(Node check){
return value==check.getValue()&&next == check.getNext();
}
/*
int main(){
int firstInt, secondInt;
std::cin>>firstInt;
Node first = Node(firstInt);
std::cout<<"Enter second int: ";
std::cin>>secondInt;
Node second = Node(secondInt, &first);
std::cout<<"Second: "<<second.getValue()<<"\nFirst: "<<(*second.getNext()).getValue();
system("pause");
}*/
Here is the linked list:
//LinkedList.cpp
LinkedList::LinkedList(void)
{
head = 0;
size = 0;
}
LinkedList::LinkedList(int value)
{
head = &Node(value);
size = 1;
}
void LinkedList::insert(int value){
if(head == 0){
Node newNode = Node(value);
head = &newNode;
std::cout<<"Adding "<<(*head).getValue()<<" as head.\n";
}else{
std::cout<<"Adding ";
Node current = *head;
int numChecked = 0;
while(size<=numChecked && (((*current.getNext()).getValue())<value)){
current = (*(current.getNext()));
numChecked++;
}
if(current.isEqual(*head)&&current.getValue()<value){
Node newNode = Node(value, &current);
std::cout<<newNode.getValue()<<" before the head: "<<current.getValue()<<"\n";
}else{
Node newNode = Node(value,current.getNext());
current.setNext(newNode);
std::cout<<newNode.getValue()<<" after "<<current.getValue()<<"\n";
}
}
size++;
}
void LinkedList::remove(int){
}
void LinkedList::print(){
Node current = *head;
std::cout<<current.getValue()<<" is the head";
int numPrinted = 0;
while(numPrinted<(size-1)){
std::cout<<(current.getValue())<<", ";
current = (*(current.getNext()));
numPrinted++;
}
}
int main(){
int a[5] = {30,20,25,13,2};
LinkedList myList = LinkedList();
int i;
for(i = 0 ; i<5 ; i++){
myList.insert(a[i]);
}
myList.print();
system("pause");
}
Any guidance would be greatly appreciated!
When you create nodes in insert, you're allocating them off the stack, which means that they'll be lost after the function returns.
Get them off the heap with:
Node * newNode=new Node(value);
When you use:
Node newNode=Node(value);
You're allocating that object on the stack, which means that pointers:
&newNode
to it are only valid until that function returns. If you use heap memory this is no longer an issue, but it does mean that you have to implement a destructor for your list which goes through and deletes each node.

What Time Is This Returning

Deep in the sauce here. I haven't worked with time to much so I'm a little confused here. I know there is FILETIME and SYSTEMTIME. What I am trying to get at this point (because it might change) are file that are less than a 20 seconds old. This returning the files and their size and something in seconds, What I'd like to know is where it is filtering by time if it is, and how can I adjust it to suit my needs. Thank you.
using namespace std;
typedef vector<WIN32_FIND_DATA> tFoundFilesVector;
std::wstring LastWriteTime;
int getFileList(wstring filespec, tFoundFilesVector &foundFiles)
{
WIN32_FIND_DATA findData;
HANDLE h;
int validResult=true;
int numFoundFiles = 0;
h = FindFirstFile(filespec.c_str(), &findData);
if (h == INVALID_HANDLE_VALUE)
return 0;
while (validResult)
{
numFoundFiles++;
foundFiles.push_back(findData);
validResult = FindNextFile(h, &findData);
}
return numFoundFiles;
}
void showFileAge(tFoundFilesVector &fileList)
{
unsigned _int64 fileTime, curTime, age;
tFoundFilesVector::iterator iter;
FILETIME ftNow;
//__int64 nFileSize;
//LARGE_INTEGER li;
//li.LowPart = ftNow.dwLowDateTime;
//li.HighPart = ftNow.dwHighDateTime;
CoFileTimeNow(&ftNow);
curTime = ((_int64) ftNow.dwHighDateTime << 32) + ftNow.dwLowDateTime;
for (iter=fileList.begin(); iter<fileList.end(); iter++)
{
fileTime = ((_int64)iter->ftLastWriteTime.dwHighDateTime << 32) + iter->ftLastWriteTime.dwLowDateTime;
age = curTime - fileTime;
cout << "FILE: '" << iter->cFileName << "', AGE: " << (_int64)age/10000000UL << " seconds" << endl;
}
}
int main()
{
string fileSpec = "*.*";
tFoundFilesVector foundFiles;
tFoundFilesVector::iterator iter;
int foundCount = 0;
getFileList(L"c:\\Mapper\\*.txt", foundFiles);
getFileList(L"c:\\Mapper\\*.jpg", foundFiles);
foundCount = foundFiles.size();
if (foundCount)
{
cout << "Found "<<foundCount<<" matching files.\n";
showFileAge(foundFiles);
}
system("pause");
return 0;
}
I don't know what you've done to try to debug this but your code doesn't work at all. The reason is you're passing getFileList() a wstring but then passing that to the ANSI version of FindFirstFile(). Unless you #define UNICODE or use the appropriate compiler option, all system calls will expect char *, not UNICODE.
The easiest fix is to simply change the declaration of getFileList() to this:
int getFileList(const char * filespec, tFoundFilesVector &foundFiles)
Change the call to FindFirstFile() to this:
h = FindFirstFile((LPCSTR)filespec, &findData);
And then change the calls to it to this:
getFileList("c:\\Mapper\\*.txt", foundFiles);
getFileList("c:\\Mapper\\*.jpg", foundFiles);
Your other option is to switch all char strings to wide chars, but either way you need to be consistent throughout. Once you do that the program works as expected.
As for your final question, your program is not filtering by time at all.
Not quite an answer, but you might want to read about file system tunneling.
It may prevent you from what you're trying to do in some situations.

Resources