область видимости динамический String array

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

если сделать глобальный массив то не видит содержимого a, b, c,

пример

String a, b, c = "";
String abc [] = {a, b, c}; 
void setup() {
}
void loop() {
}

а если локально то все ок

String a, b, c = "";
void setup() {
}
void loop() {
}
void abc() {
String abc [] = {a, b, c}; 
]

в чем проблема?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Кто не видит? Кого не видит? Как удалось выяснить, что не видит? Приведите скетч из которого явно следует, что кто-то кого-то не видит. Приведёте скечт, иллюстрирующий проблему - тогда и поговорим.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015
String a, b, c = "";
String abc [] = {a, b, c}; //глобальная область видимости
void setup() {
Serial.begin(9600);
}
void loop() {
a = "1234567890"; //переменные a, b, c
b = "0987654321";
c = "admin";
for (int i = 0; i < 3; i++) {
Serial.println(abc[i]);  // печатает пустоту
}
}

так не работает

String a, b, c = "";
void setup() {
Serial.begin(9600);
}
void loop() {
a = "1234567890";
b = "0987654321";
c = "admin";
abc ();
}
void abc () {
String abc [] = {a, b, c}; // локальная область видимости
for (int i = 0; i < 3; i++) {
Serial.println(abc[i]); // печатает все как надо
}

так работает

Клапауций 666
Offline
Зарегистрирован: 10.11.2015

Valera19701 пишет:

String a, b, c = "";
String abc [] = {a, b, c}; //глобальная область видимости

так не работает

ясен пень, что не работает - помоги мне развидеть строку, где символами являются объекты класса.

String abc [] = {String a, String b, String c};

 

 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

да понял уже

можно и так

String a, b, c = "";
String abc [3]; 
void setup() {
Serial.begin(9600);
}
void loop() {
a = "1234567890";
b = "0987654321";
c = "admin";
abc[0] = a;
abc[1] = b;
abc[2] = c;
for (int i = 0; i < 3; i++) {
Serial.println(abc[i]); // печатает все как надо
}

 

Клапауций 666
Offline
Зарегистрирован: 10.11.2015
// String a, b, c = "";
String abc[3]; 
void setup() {
Serial.begin(9600);
}
void loop() {
// a = "1234567890";
// b = "0987654321";
// c = "admin";
// abc[0] = a;
// abc[1] = b;
// abc[2] = c;
abc[0] = "1234567890";
abc[1] = "0987654321";
abc[2] = "admin";
for (int i = 0; i < 3; i++) {
Serial.println(abc[i]); // печатает все как надо
}
}

 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

в том то и вся соль, что a, b, c меняющиеся переменные считаные из eeprom и в процессе работы могут менятся и записываться в eeprom, то я для примера привел

Клапауций 666
Offline
Зарегистрирован: 10.11.2015

Valera19701 пишет:

в том то и вся соль, что a, b, c меняющиеся переменные считаные из eeprom и в процессе работы могут менятся и записываться в eeprom

ок

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Значит история ещё не закончилась, без попкорна не обойтись.

Клапауций 666
Offline
Зарегистрирован: 10.11.2015

kisoft пишет:
Значит история ещё не закончилась, без попкорна не обойтись.

закончилась - дальше можно выпиливать избыточность по реальному коду.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Присаживайся пока, попкорна пожуем, человек держит в массиве копии переменных a, b, c. Поменяет a, b или c, а в массиве ничего не изменится. Хотя нужен массив указателей или ссылок на переменные a, b, c, тогда и заработает как надо.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Valera19701 пишет:
так работает

Не-а! Не работает. Вы не то протестировали. Вот, смотрите, я после Вашей печати меняю a и ещё раз печатаю и ... какая боль, ни хрена не поменялось :(

String a, b, c = "";

void setup() {
	Serial.begin(19200);
}
void loop() {
	a = "1234567890";
	b = "0987654321";
	c = "admin";
	abc ();
}

void abc () {
	String abc [] = {a, b, c}; // локальная область видимости
	for (int i = 0; i < 3; i++) {
		Serial.println(abc[i]); // печатает все как надо
	}
	a = "5:0"; // Какая боль!
	Serial.println("Must be a=5:0");
	for (int i = 0; i < 3; i++) {
		Serial.println(abc[i]); // печатает НЕ все как надо
	}
}

На самом деле Ваш первый вариант ничем не отличается от второго - ошибка одна и та же и не работают они одинаково. Вам показалось, что типа работает из-за того, что Вы сжульничали - поменяли последовательность действий.

И никакого отношения к области видимости Ваша ошибка не имеет - абсолютно никакого.

Запомните, объекты (а String - это объект) нельзя так просто присваивать друг другу, как числа (а в инициализации массива Вы именно присваиваете). Вернее, присваивать-то можно, но нужно понимать механизм присваивания объектов (он совсем не такой. как у чисел) и не удивляться, когда они присваиваются по своим правилам, а не по правилам присваивания чисел. Я не буду здесь читать Вам лекцию об устройстве объетков - Страуструп Вам в помощь, я же попробую догадаться чего Вы хотели.

Вы хотели к одним и тем же строкам обращаться и как к отдельным переменным, и как к элементам массива, правильно? Если так, то ... я не спрашиваю для чего Вам это надо, потому что уверен, что на самом Вам это не нужно, а желание так сделать - следствие какого-то другого заблуждения. Впрочем, хотите - значит зачем-то нужно.

Такое извращение можно сделать 100500 способами, например можно обзозвать a, b и c ссылками и сделать, чтобы они ссылались на элементы массива. Например,

String abc [3];
String &a = abc[0], &b = abc[1], &c = abc[2];


void setup() {
	Serial.begin(19200);
	while(!Serial) yield();
	Serial.println("Fun begins!");
}

void loop() {
	a = "aaa"; 
	b = "bbb";
	c = "ccc";
	for (int i = 0; i < 3; i++) Serial.println(abc[i]);
	delay(100500);	
}

есть ещё 100500-1 способ сделать это, но я пока ограничусь одним примером, тем более, что я не понимаю для чего это Вам.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

я сделал функцией, она вызывается когда мне надо и собирает массив

void abc () {
String abc [] = {a, b, c}; 
for (int i = 0; i < 3; i++) {
Serial.println(abc[i]); 
}

может и неправильно , но работает (сильно не пинать, занимаюсь ардуиной всего пару месяцев)

если есть какие то подсказки пишите, не стесняйтесь

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

ЕвгенийП спасибо за подсказку!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да ни фига ж не работает! Вы мой пример (первый скетч в моём посте) смотрели? Как же работает, когда значение поменять нельзя???.

Ладно, давайте чуть подробнее.

Когда Вы присваиваете стринги в инициализации, вы на самом деле создаёте новые объекты - копии старых (ваших переменных).

Потому Вам и кажется что работает - Вы создали новый обект в элементе массива - копию переменной и вроде она печатается, т.к. она ж такая же - копия! Но теперь поменяйте переменную (что я и сделал в своём примере) - элемент массива и не подумает меняться - он ведь самостоятельный объект! Он так иостанется тем, чем был и это чётко видно в моём примере.

Вы понимаете о чём я? 

Посмотрите первый скетч из моего поста. Если бы у Вас всё работало, то и мои 5:0 присвоились бы, но они же не присвоились!

А вот во втором скетче я сделал ссылки - там не создаются новые объекты, а заводятся ссылки на на Ваши переменные и там действительно всё работает, т.к. элемент массива не является самостоятельным объектом, а просто ссылается на переменную.

В общем, берите Страуструпа и читайте.

 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

и еще вопрос, как правильно подсчитать кол-во заполненых строк в массиве,, исключая пустые

int num = (num, sizeof(abc) / sizeof (String)); это кол-во строк

а как исключить пустые?

Клапауций 666
Offline
Зарегистрирован: 10.11.2015

да, что за дурь?


String a;
String b;
String c;

void setup() {
Serial.begin(9600);
}

void loop() {
a = "1234567890";
b = "0987654321";
c = "admin";
abc();
}

void abc() {
Serial.println(a);
Serial.println(b);
Serial.println(c);
}

*Страуструп-чмо.

Клапауций 666
Offline
Зарегистрирован: 10.11.2015

Valera19701 пишет:

и еще вопрос, как правильно подсчитать кол-во заполненых строк в массиве,, исключая пустые

int num = (num, sizeof(abc) / sizeof (String)); это кол-во строк

а как исключить пустые?

пустые это String a, b, c = ""; ?

ну, они как бы не пустые - они содержат символ '\0', насколько правильно я понимаю концепцию String.

исключить - поменять местами с "непустой" строкой? что бы что?

 

griin
Offline
Зарегистрирован: 19.04.2015
01 String a, b, c = "";
02 String abc [] = {a, b, c}; //глобальная область видимости
03 void setup() {
04 Serial.begin(9600);
05 }
06 void loop() {
07 a = "1234567890"//переменные a, b, c
08 b = "0987654321";
09

c = "admin";

abc[0] = a;

abc[1] = b;

abc[2] = c;

10 for (int i = 0; i < 3; i++) {
11 Serial.println(abc[i]);  // печатает пустоту
12 }
13 }

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

griin, ну, Вы после присваивания значений переменным, заново всунули их в массив. А если придётся ещё раз переменную поменять, Снова её элементу массива присваивать?

Нет, не зря kisoft про попкорн говорил, надо бы тоже запастись.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Valera19701 пишет:

и еще вопрос, как правильно подсчитать кол-во заполненых строк в массиве,, исключая пустые

int num = (num, sizeof(abc) / sizeof (String)); это кол-во строк

а как исключить пустые?

Жутко интересно, как Вы понимаете выражение:

int num = (num, sizeof(abc) / sizeof(String)); // это кол-во строк

Вы понимаете как это работает? Можете объяснить?

Если нужно количество элементов в массиве, то почему так и не написать:

int num = sizeof(abc) / sizeof(String); // это кол-во строк

Это чем-то некошерно? Не наш метод, типа?

------------------

Посчитать количество непустых строк можно самым обыкновенным циклом. Просто идём по массиву и считаем сколько там строк ненулевой длины. Ну, как-то так ...

String abc [3];
String &a = abc[0], &b = abc[1], &c = abc[2];


void setup() {
	Serial.begin(19200);
	while(!Serial) yield();
	Serial.println("Fun begins!");
	a = "kaka";
	b = "mumu";
	short NotEmpty = 0;
	for (size_t i = 0, total = sizeof(abc)/sizeof(abc[0]); i < total; i++) {
		if (abc[i].length() > 0) NotEmpty++;
	}
	Serial.println(NotEmpty);
}

void loop() {
}

А вот последний вопрос нуждается в уточнении. Что значит "исключить пустые"? Выбросить их из массива, чтобы их там не было? Или просто не обрабатывать? Если второе, то так же в цикле смотрите на длину и если ноль, то не обрабатываете. Если первое, то ... проще было не добавлять :) Удаление из массива операция дорогая и её по-возможности избегают. Если нужен "массив" из которого надо часто удалять, то делают его не массивом. а списком.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

вы тут все требуете рассказать что я пытаюсь сделать, вообщем так a,b,c это телефоные номера, их может быть от 1 до 3, вот надо чтобы в sms отправлялку не попадали пустые номера телефонов

void SendMessage(String text) {
 // тут надо обрезать пустые номера
  for (byte i = 0; i < (тут надо указать кол-во не пустых номеров); i++) {
    gprs.print("AT+CMGF=1\r");
    delay(200);
    gprs.println("AT+CMGS=\"" + abc[i] + "\"");
    delay(200);
    gprs.println(text);
    delay(200);
    gprs.println((char)26);
    delay(5000);
  }
}

как то так

Клапауций 666
Offline
Зарегистрирован: 10.11.2015

на - писал для себя заметку по String

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
b.length();        // возвращает число знаков в строке b.
b.remove(n);       // удаление n-го символа из строки b.
b.charAt(n);       // возвращает значение n-го символа строки b.
b.setCharAt(n, m); // заменяет n-й символ строки b на символ m.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

только не забывай, что каждая строка содержит в конце символ '\0' - нужно корректировать +1 если нужно знать реальный размер строки.

*и прекращай эту дурь с массивом из трёх строк.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

Клапауций 666 пишет:

*и прекращай эту дурь с массивом из трёх строк.

 :), иду за пузырем, буду разбираться

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Valera19701 пишет:

вы тут все требуете рассказать что я пытаюсь сделать, вообщем так a,b,c это телефоные номера, их может быть от 1 до 3, вот надо чтобы в sms отправлялку не попадали пустые номера телефонов

void SendMessage(String text) {
 // тут надо обрезать пустые номера
  for (byte i = 0; i < (тут надо указать кол-во не пустых номеров); i++) {

как то так

Не надо ни обрезать, ни указывать. Надо просто проверять, если длина больше нуля - отправлять, если равно нулю - пропускать. В примере отправку надо вставить вместо многоточия. По ходу дела печатается на какие номера отправляется, а в конце печатается на какое количество номеров отправлено.

String abc [3];
String &a = abc[0], &b = abc[1], &c = abc[2];


void setup() {
	Serial.begin(19200);
	while(!Serial) yield();
	Serial.println("Fun begins!");
	a = "kaka";
	b = "mumu";
	short NotEmpty = 0;
	for (size_t i = 0, total = sizeof(abc)/sizeof (abc[0]); i < total; i++) {
		if (abc[i].length() > 0) {
			NotEmpty++;
			Serial.println("Sending SMS to number: ");
			Serial.print(abc[i]);
			// Отправляем смс по номеру, сидящему в abc[i]
			// ...
		}
	}
	Serial.print(NotEmpty);
	Serial.println(" SMS'es sent.");
}

void loop() {
}

Теперь про Вашу функцию. Вы ей в параметрах записали одну строку, а не массив. Так что у Вас номера всё=таки в массиве или в одной строке сидят?

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

в массиве

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А функции строку SendMessage передаёте. Может Вы её хотите вызывать уже для конкретного номера? Тогда зачем в ней цикл по номерам? Если её передаётся один номер, то не надо никакого цикла, просто проверяйте не путой ли он и, если не пустой, отправляйте.

В общем, разбирайтесь, у Вас тут каша какая-то. Как проверить не пустой ли номер. я Вам показал.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

ЕвгенийП пишет:

А функции строку SendMessage передаёте. Может Вы её хотите вызывать уже для конкретного номера? Тогда зачем в ней цикл по номерам? Если её передаётся один номер, то не надо никакого цикла, просто проверяйте не путой ли он и, если не пустой, отправляйте.

В общем, разбирайтесь, у Вас тут каша какая-то. Как проверить не пустой ли номер. я Вам показал.

да, я тоже подумал чтобы убраь массив, и отправлять с проверкй на пустую строку

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

сделал так, все работает нормально

void SendMessage(String text) {
  if (a.length() > 0) {
    for (byte i = 0; i < 1; i++) {
      gprs.print("AT+CMGF=1\r");
      delay(200);
      gprs.println("AT+CMGS=\"" + a + "\"");
      delay(200);
      gprs.println(text);
      delay(200);
      gprs.println((char)26);
      delay(5000);
    }
  }
  if (b.length() > 0) {
    for (byte i = 0; i < 1; i++) {
      gprs.print("AT+CMGF=1\r");
      delay(200);
      gprs.println("AT+CMGS=\"" + b + "\"");
      delay(200);
      gprs.println(text);
      delay(200);
      gprs.println((char)26);
      delay(5000);
    }
  }
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Странно как-то.

Где у Вас номер телефона сидит? В a и b? А в text - сидит текст смс-ки?

А номер в c решили не проверять или ещё третий блок допишете? И вообще, зачем два (или тем более три) одинаковых блока? Не проще ли добавить ещё один параметр и дважды вызвать функцию?

Кроме того, что за странная конструкция 

for (byte i = 0; i < 1; i++)

её можно просто убрать (как и закрывающую скобку в строках 12 и 24 - ничего не изменится.

Клапауций 666
Offline
Зарегистрирован: 10.11.2015

ну, говорит, что три номера ему нужно одновременно хратить в переменных еепрома.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

ЕвгенийП пишет:

Странно как-то.

Где у Вас номер телефона сидит? В a и b? А в text - сидит текст смс-ки?

А номер в c решили не проверять или ещё третий блок допишете? И вообще, зачем два (или тем более три) одинаковых блока? Не проще ли добавить ещё один параметр и дважды вызвать функцию?

 номер сидит в a и b , text  это текст смски

а два блока из-за динамической памяти, пусть на флэше будет больше, чем добавлять переменную

for (byte i = 0; i < 1; i++)

это блокировка на одно срабатывание

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Valera19701 пишет:

а два блока из-за динамической памяти, пусть на флэше будет больше, чем добавлять переменную

Так она ж на стеке добавляется - как добавилась, так и убралась. А два блока - это чтобы, когда нужно будет внести изменения, забыть один из них поправить и нажить проблем :)
 
Впрочем, Вам виднее.

Valera19701 пишет:

for (byte i = 0; i < 1; i++)

это блокировка на одно срабатывание

Нет, это не блокировка - это абсолютно ненужный код, которые абсолютно ни на что не влияет - просто ни на что.
Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

ЕвгенийП пишет:

Так она ж на стеке добавляется - как добавилась, так и убралась. А два блока - это чтобы, когда нужно будет внести изменения, забыть один из них поправить и нажить проблем :)

у меня еще в коде конструктор смс

ненужный код убрал

 

Andrey12
Andrey12 аватар
Offline
Зарегистрирован: 26.12.2014

просто подпишусь, интересная тема.