почему printf показывает 0 для векторного размера, когда cout показывает правильный размер? - PullRequest
1 голос
/ 02 марта 2009

Я не понимаю, почему я получаю 0, когда я использую printf и% d, чтобы получить размер моего вектора:

vector<long long> sieve;
int size;
...
//add stuff to vector
...
size = sieve.size();
printf("printf sieve size: %d \n", size); //prints "printf sieve size: 0"
std::cout << "cout sieve size: ";
std::cout << size;
std::cout << " \n ";
//prints "cout sieve size: 5 (or whatever the correct sieve size is)"

Если я переберу вектор через

if(i=0;i<sieve.size();i++) 

Я получил правильное количество итераций.

Что я делаю неправильно или что не так с printf? size () возвращает int вправо ??


Вот весь мой маленький сценарий:

#include <iostream>
#include <vector>
#include <stack>
#include <math.h>

int main (int argc, char * const argv[]) {
    unsigned long long answer = 0;
    unsigned long long cur = 2;
    std::vector<long long> sieve;
    unsigned long long limit;
    unsigned long long value;
    unsigned int i;
    int size;
    bool isPrime;
    std::cout << "Provide a value to find its largest prime factor: ";
    std::cin >> value;
    limit = ceil(sqrt(value));
    sieve.push_back(2);
    while(cur++ < limit){
      isPrime = true;
      sieve.begin();
      for(i=0; i<sieve.size();i++){
        if(!(cur % sieve[i])){
          isPrime = false;
          break;
        }
      }
      if(isPrime){  
        if(!(value % cur)){
          std::printf("Is prime factor: %d\n", cur);
          sieve.push_back(cur);
          answer = sieve[sieve.size() - 1];
          size = sieve.size();
          std::printf("current last: %d sieve size: %ld\n", answer, size);
          for(i=0; i<sieve.size();i++){
            std::printf("sieve iter: %d sieve val: %d\n", i, sieve[i]);
            std::cout << size;
            std::cout << " wtf\n";
          }
        }
      }
    }
    answer = sieve[sieve.size() - 1];
    size = sieve.size();
    std::printf("Limit: %d Answer: %d sieve size: %ld\n", limit, answer, size);
    return 0;
}

Ответы [ 8 ]

6 голосов
/ 02 марта 2009

Теперь, с полным источником, это понятно.

Вы заявили:

int size;

Тогда вы использовали:

std::printf("current last: %d sieve size: %ld\n", answer, size);
std::printf("Limit: %d Answer: %d sieve size: %ld\n", limit, answer, size);

Если size - int, вы должны использовать «% d», а не «% ld». Хороший компилятор предупредил бы вас об этом. GCC выдает эти предупреждения для вашей оригинальной версии:

test.cpp: In function ‘int main(int, char* const*)’:
test.cpp:17: warning: converting to ‘long long unsigned int’ from ‘double’
test.cpp:30: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long long unsigned int’
test.cpp:34: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long long unsigned int’
test.cpp:34: warning: format ‘%ld’ expects type ‘long int’, but argument 3 has type ‘int’
test.cpp:36: warning: format ‘%d’ expects type ‘int’, but argument 3 has type ‘long long int’
test.cpp:45: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long long unsigned int’
test.cpp:45: warning: format ‘%d’ expects type ‘int’, but argument 3 has type ‘long long unsigned int’
test.cpp:45: warning: format ‘%ld’ expects type ‘long int’, but argument 4 has type ‘int’

Это многое говорит.

Вы должны объявить размер как:

std::vector<long long>::size_type size;

Тогда вы должны использовать его как:

std::printf("current last: %llu sieve size: %llu\n", (unsigned long long) answer, (unsigned long long) size);
std::printf("Limit: %llu Answer: %llu sieve size: %llu\n", (unsigned long long) limit, (unsigned long long) answer, (unsigned long long) size);

Конечно, использование iostream позволяет избежать этих проблем, особенно уродливого приведения в printf () для преобразования размера в тип, известный для printf.

5 голосов
/ 02 марта 2009

Это испорчено, потому что у вас есть:

unsigned long long answer = 0;
int size;

и вы звоните printf с:

std::printf("current last: %d sieve size: %ld\n", answer, size);

Обе строки формата неверны:

  1. Вы передаете answer в printf и форматируете его %d, но это должно быть %lld, поскольку оно объявлено unsigned long long.

  2. Вы передаете размер с %d вместо %ld. Поскольку size есть и int, оно должно быть %d.

Когда эти аргументы передаются в printf, он печатает первые 32 бита answer для первого %d и вторые 32 бита (или больше, после конца!) answer для %ld , Это не , что вы хотите.

Если вы компилируете с -Wall, ваш компилятор должен предупредить вас об этом. Обратите особое внимание на предупреждения!

2 голосов
/ 02 марта 2009

Ваша проблема в том, что answer определяется как long long, и вы печатаете его только с %d.

printf - это функция varargs, а в Си это означает, что компилятор не знает какие аргументы вы передали в функцию. Он не может выполнять обычные преобразования типов и должен доверять своему пользователю, чтобы получить правильные аргументы формата, иначе эти аргументы не будут правильно извлечены из стека вызовов.

Вы не правильно поняли.

2 голосов
/ 02 марта 2009

выглядит сумасшедшим. Поскольку размер объявлен как "int size", printf ("...% d") определенно корректен. Нельзя сказать, что size_t отличается от размера «int», поскольку вы явно объявляете «size» как int, и cout

Вы проверили, что вы включили? Возможно, без правильного объявления в вашей системе printf работает «неправильно».

1 голос
/ 02 марта 2009

Метод size() возвращает size_t, что зависит от вашей реализации c ++. Когда вы пытаетесь printf("%d"), вы говорите библиотеке ожидать int, что не всегда так; затем он берет int из стека вызовов, который принимает только старшие байты size_t.

Что вам нужно сделать, это принудительно вернуть возвращаемое значение size() в известный тип данных с помощью приведения: printf("%d", (int) size)

1 голос
/ 02 марта 2009

На каком оборудовании вы работаете? Скорее всего, size это другой тип, чем вы думаете. Напечатайте sizeof(size) и проверьте или попробуйте %ld. Если у вас есть машина с прямым порядком байтов, например, PPC, размер - long, и вы печатаете %d, вы получаете конец длинных с нулем.

обновление

Хорошо, вот что я получаю с Intel Mac mini, 10.5:

$ cat trySize.C 
#include <iostream>
#include <vector>

int main(){
    std::cout << "sizeof(size_t): " 
        << sizeof(size_t) 
        << std::endl ;
    std::vector<long long> sieve ;
    std::cout << "sizeof(sieve.size()): " 
        << sizeof(sieve.size()) 
        << std::endl;
    printf("sizeof(sieve.size()) (printf): %d\n", sizeof(sieve.size()));
    return 0;
}
$ g++ trySize.C
$ ./a.out
sizeof(size_t): 4
sizeof(sieve.size()): 4
sizeof(sieve.size()) (printf): 4
$ 

Вы, вероятно, должны начать разбивать код на более мелкие части и пробовать их; здесь есть что-то странное.

1 голос
/ 02 марта 2009

векторные размеры size_t, которые, как я полагаю, обычно long ...

Не могу сказать, почему printf не работает.

0 голосов
/ 02 марта 2009

Это будет работать:

std::printf("current last: %**lld** sieve size: %ld\n", answer, size);

Проблема в том, что ответ - long long (64-разрядное целое число), и% d ожидает 32-разрядное целое число. Таким образом, размер не печатается. Вам нужно будет использовать% lld.

Для получения дополнительной информации о форматных строках для printf проверьте: http://en.wikipedia.org/wiki/Printf

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...